import: Apply generic patches from qsdk.

for i in $(ls <qsdk>/target/linux/generic/patches-3.3/*); do
	patch -p1 <$i;
done

Change-Id: Ia9befdeb17b1002efe62c6dfa8ada8dc1f54a073
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index a0ffac0..a09f00d 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -71,20 +71,6 @@
 
 ---------------------------
 
-What:	IRQF_SAMPLE_RANDOM
-Check:	IRQF_SAMPLE_RANDOM
-When:	July 2009
-
-Why:	Many of IRQF_SAMPLE_RANDOM users are technically bogus as entropy
-	sources in the kernel's current entropy model. To resolve this, every
-	input point to the kernel's entropy pool needs to better document the
-	type of entropy source it actually is. This will be replaced with
-	additional add_*_randomness functions in drivers/char/random.c
-
-Who:	Robin Getz <rgetz@blackfin.uclinux.org> & Matt Mackall <mpm@selenic.com>
-
----------------------------
-
 What:	The ieee80211_regdom module parameter
 When:	March 2010 / desktop catchup
 
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index 4fca82e..42b0539 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -62,6 +62,7 @@
 	int (*removexattr) (struct dentry *, const char *);
 	void (*truncate_range)(struct inode *, loff_t, loff_t);
 	int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, u64 len);
+	struct file *(*open)(struct dentry *,struct file *,const struct cred *);
 
 locking rules:
 	all may block
@@ -89,6 +90,7 @@
 removexattr:	yes
 truncate_range:	yes
 fiemap:		no
+open:		no
 	Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on
 victim.
 	cross-directory ->rename() has (per-superblock) ->s_vfs_rename_sem.
diff --git a/Documentation/filesystems/overlayfs.txt b/Documentation/filesystems/overlayfs.txt
new file mode 100644
index 0000000..7161dc3
--- /dev/null
+++ b/Documentation/filesystems/overlayfs.txt
@@ -0,0 +1,199 @@
+Written by: Neil Brown <neilb@suse.de>
+
+Overlay Filesystem
+==================
+
+This document describes a prototype for a new approach to providing
+overlay-filesystem functionality in Linux (sometimes referred to as
+union-filesystems).  An overlay-filesystem tries to present a
+filesystem which is the result over overlaying one filesystem on top
+of the other.
+
+The result will inevitably fail to look exactly like a normal
+filesystem for various technical reasons.  The expectation is that
+many use cases will be able to ignore these differences.
+
+This approach is 'hybrid' because the objects that appear in the
+filesystem do not all appear to belong to that filesystem.  In many
+cases an object accessed in the union will be indistinguishable
+from accessing the corresponding object from the original filesystem.
+This is most obvious from the 'st_dev' field returned by stat(2).
+
+While directories will report an st_dev from the overlay-filesystem,
+all non-directory objects will report an st_dev from the lower or
+upper filesystem that is providing the object.  Similarly st_ino will
+only be unique when combined with st_dev, and both of these can change
+over the lifetime of a non-directory object.  Many applications and
+tools ignore these values and will not be affected.
+
+Upper and Lower
+---------------
+
+An overlay filesystem combines two filesystems - an 'upper' filesystem
+and a 'lower' filesystem.  When a name exists in both filesystems, the
+object in the 'upper' filesystem is visible while the object in the
+'lower' filesystem is either hidden or, in the case of directories,
+merged with the 'upper' object.
+
+It would be more correct to refer to an upper and lower 'directory
+tree' rather than 'filesystem' as it is quite possible for both
+directory trees to be in the same filesystem and there is no
+requirement that the root of a filesystem be given for either upper or
+lower.
+
+The lower filesystem can be any filesystem supported by Linux and does
+not need to be writable.  The lower filesystem can even be another
+overlayfs.  The upper filesystem will normally be writable and if it
+is it must support the creation of trusted.* extended attributes, and
+must provide valid d_type in readdir responses, at least for symbolic
+links - so NFS is not suitable.
+
+A read-only overlay of two read-only filesystems may use any
+filesystem type.
+
+Directories
+-----------
+
+Overlaying mainly involved directories.  If a given name appears in both
+upper and lower filesystems and refers to a non-directory in either,
+then the lower object is hidden - the name refers only to the upper
+object.
+
+Where both upper and lower objects are directories, a merged directory
+is formed.
+
+At mount time, the two directories given as mount options are combined
+into a merged directory:
+
+  mount -t overlayfs overlayfs -olowerdir=/lower,upperdir=/upper /overlay
+
+Then whenever a lookup is requested in such a merged directory, the
+lookup is performed in each actual directory and the combined result
+is cached in the dentry belonging to the overlay filesystem.  If both
+actual lookups find directories, both are stored and a merged
+directory is created, otherwise only one is stored: the upper if it
+exists, else the lower.
+
+Only the lists of names from directories are merged.  Other content
+such as metadata and extended attributes are reported for the upper
+directory only.  These attributes of the lower directory are hidden.
+
+whiteouts and opaque directories
+--------------------------------
+
+In order to support rm and rmdir without changing the lower
+filesystem, an overlay filesystem needs to record in the upper filesystem
+that files have been removed.  This is done using whiteouts and opaque
+directories (non-directories are always opaque).
+
+The overlay filesystem uses extended attributes with a
+"trusted.overlay."  prefix to record these details.
+
+A whiteout is created as a symbolic link with target
+"(overlay-whiteout)" and with xattr "trusted.overlay.whiteout" set to "y".
+When a whiteout is found in the upper level of a merged directory, any
+matching name in the lower level is ignored, and the whiteout itself
+is also hidden.
+
+A directory is made opaque by setting the xattr "trusted.overlay.opaque"
+to "y".  Where the upper filesystem contains an opaque directory, any
+directory in the lower filesystem with the same name is ignored.
+
+readdir
+-------
+
+When a 'readdir' request is made on a merged directory, the upper and
+lower directories are each read and the name lists merged in the
+obvious way (upper is read first, then lower - entries that already
+exist are not re-added).  This merged name list is cached in the
+'struct file' and so remains as long as the file is kept open.  If the
+directory is opened and read by two processes at the same time, they
+will each have separate caches.  A seekdir to the start of the
+directory (offset 0) followed by a readdir will cause the cache to be
+discarded and rebuilt.
+
+This means that changes to the merged directory do not appear while a
+directory is being read.  This is unlikely to be noticed by many
+programs.
+
+seek offsets are assigned sequentially when the directories are read.
+Thus if
+  - read part of a directory
+  - remember an offset, and close the directory
+  - re-open the directory some time later
+  - seek to the remembered offset
+
+there may be little correlation between the old and new locations in
+the list of filenames, particularly if anything has changed in the
+directory.
+
+Readdir on directories that are not merged is simply handled by the
+underlying directory (upper or lower).
+
+
+Non-directories
+---------------
+
+Objects that are not directories (files, symlinks, device-special
+files etc.) are presented either from the upper or lower filesystem as
+appropriate.  When a file in the lower filesystem is accessed in a way
+the requires write-access, such as opening for write access, changing
+some metadata etc., the file is first copied from the lower filesystem
+to the upper filesystem (copy_up).  Note that creating a hard-link
+also requires copy_up, though of course creation of a symlink does
+not.
+
+The copy_up may turn out to be unnecessary, for example if the file is
+opened for read-write but the data is not modified.
+
+The copy_up process first makes sure that the containing directory
+exists in the upper filesystem - creating it and any parents as
+necessary.  It then creates the object with the same metadata (owner,
+mode, mtime, symlink-target etc.) and then if the object is a file, the
+data is copied from the lower to the upper filesystem.  Finally any
+extended attributes are copied up.
+
+Once the copy_up is complete, the overlay filesystem simply
+provides direct access to the newly created file in the upper
+filesystem - future operations on the file are barely noticed by the
+overlay filesystem (though an operation on the name of the file such as
+rename or unlink will of course be noticed and handled).
+
+
+Non-standard behavior
+---------------------
+
+The copy_up operation essentially creates a new, identical file and
+moves it over to the old name.  The new file may be on a different
+filesystem, so both st_dev and st_ino of the file may change.
+
+Any open files referring to this inode will access the old data and
+metadata.  Similarly any file locks obtained before copy_up will not
+apply to the copied up file.
+
+On a file is opened with O_RDONLY fchmod(2), fchown(2), futimesat(2)
+and fsetxattr(2) will fail with EROFS.
+
+If a file with multiple hard links is copied up, then this will
+"break" the link.  Changes will not be propagated to other names
+referring to the same inode.
+
+Symlinks in /proc/PID/ and /proc/PID/fd which point to a non-directory
+object in overlayfs will not contain vaid absolute paths, only
+relative paths leading up to the filesystem's root.  This will be
+fixed in the future.
+
+Some operations are not atomic, for example a crash during copy_up or
+rename will leave the filesystem in an inconsitent state.  This will
+be addressed in the future.
+
+Changes to underlying filesystems
+---------------------------------
+
+Offline changes, when the overlay is not mounted, are allowed to either
+the upper or the lower trees.
+
+Changes to the underlying filesystems while part of a mounted overlay
+filesystem are not allowed.  If the underlying filesystem is changed,
+the behavior of the overlay is undefined, though it will not result in
+a crash or deadlock.
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index 3d9393b..3c65a0f 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -364,6 +364,8 @@
 	ssize_t (*listxattr) (struct dentry *, char *, size_t);
 	int (*removexattr) (struct dentry *, const char *);
 	void (*truncate_range)(struct inode *, loff_t, loff_t);
+	struct file *(*open) (struct dentry *, struct file *,
+			      const struct cred *);
 };
 
 Again, all methods are called without any locks being held, unless
@@ -475,6 +477,12 @@
   truncate_range: a method provided by the underlying filesystem to truncate a
   	range of blocks , i.e. punch a hole somewhere in a file.
 
+  open: this is an alternative to f_op->open(), the difference is that this
+	method may return any open file, not necessarily originating from the
+	same filesystem as the one i_op->open() was called on.  It may be useful
+	for stacking filesystems which want to allow native I/O directly on
+	underlying files.
+
 
 The Address Space Object
 ========================
diff --git a/Documentation/gpio.txt b/Documentation/gpio.txt
index 792faa3..9e28c05 100644
--- a/Documentation/gpio.txt
+++ b/Documentation/gpio.txt
@@ -303,6 +303,9 @@
 	* GPIOF_INIT_LOW	- as output, set initial level to LOW
 	* GPIOF_INIT_HIGH	- as output, set initial level to HIGH
 
+	* GPIOF_EXPORT_DIR_FIXED	- export gpio to sysfs, keep direction
+	* GPIOF_EXPORT_DIR_CHANGEABLE	- also export, allow changing direction
+
 since GPIOF_INIT_* are only valid when configured as output, so group valid
 combinations as:
 
diff --git a/Documentation/gpiommc.txt b/Documentation/gpiommc.txt
new file mode 100644
index 0000000..8e53222
--- /dev/null
+++ b/Documentation/gpiommc.txt
@@ -0,0 +1,97 @@
+GPIOMMC - Driver for an MMC/SD card on a bitbanging GPIO SPI bus
+================================================================
+
+The gpiommc module hooks up the mmc_spi and spi_gpio modules for running an
+MMC or SD card on GPIO pins.
+
+Two interfaces for registering a new MMC/SD card device are provided:
+A static platform-device based mechanism and a dynamic configfs based interface.
+
+
+Registering devices via platform-device
+=======================================
+
+The platform-device interface is used for registering MMC/SD devices that are
+part of the hardware platform. This is most useful only for embedded machines
+with MMC/SD devices statically connected to the platform GPIO bus.
+
+The data structures are declared in <linux/mmc/gpiommc.h>.
+
+To register a new device, define an instance of struct gpiommc_platform_data.
+This structure holds any information about how the device is hooked up to the
+GPIO pins and what hardware modes the device supports. See the docbook-style
+documentation in the header file for more information on the struct fields.
+
+Then allocate a new instance of a platform device by doing:
+
+	pdev = platform_device_alloc(GPIOMMC_PLATDEV_NAME, gpiommc_next_id());
+
+This will allocate the platform device data structures and hook it up to the
+gpiommc driver.
+Then add the gpiommc_platform_data to the platform device.
+
+	err = platform_device_add_data(pdev, pdata, sizeof(struct gpiommc_platform_data));
+
+You may free the local instance of struct gpiommc_platform_data now. (So the
+struct may be allocated on the stack, too).
+Now simply register the platform device.
+
+	err = platform_device_add(pdev);
+
+Done. The gpiommc probe routine will be invoked now and you should see a kernel
+log message for the added device.
+
+
+Registering devices via configfs
+================================
+
+MMC/SD cards connected via GPIO often are a pretty dynamic thing, as for example
+selfmade hacks for soldering an MMC/SD card to standard GPIO pins on embedded
+hardware are a common situation.
+So we provide a dynamic interface to conveniently handle adding and removing
+devices from userspace, without the need to recompile the kernel.
+
+The "gpiommc" subdirectory at the configfs mountpoint is used for handling
+the dynamic configuration.
+
+To create a new device, it must first be allocated with mkdir.
+The following command will allocate a device named "my_mmc":
+	mkdir /config/gpiommc/my_mmc
+
+There are several configuration files available in the new
+/config/gpiommc/my_mmc/ directory:
+
+gpio_data_in			= The SPI data-IN GPIO pin number.
+gpio_data_out			= The SPI data-OUT GPIO pin number.
+gpio_clock			= The SPI Clock GPIO pin number.
+gpio_chipselect			= The SPI Chipselect GPIO pin number.
+gpio_chipselect_activelow	= Boolean. If 0, Chipselect is active-HIGH.
+				  If 1, Chipselect is active-LOW.
+spi_mode			= The SPI data mode. Can be 0-3.
+spi_delay			= Enable all delays in the lowlevel bitbanging.
+max_bus_speed			= The maximum SPI bus speed. In Hertz.
+
+register			= Not a configuration parameter.
+				  Used to register the configured card
+				  with the kernel.
+
+The device must first get configured and then registered by writing "1" to
+the "register" file.
+The configuration parameters "gpio_data_in", "gpio_data_out", "gpio_clock"
+and "gpio_chipselect" are essential and _must_ be configured before writing
+"1" to the "register" file. The registration will fail, otherwise.
+
+The default values for the other parameters are:
+gpio_chipselect_activelow	= 1		(CS active-LOW)
+spi_mode			= 0		(SPI_MODE_0)
+spi_delay			= 1		(enabled)
+max_bus_speed			= 5000000	(5 Mhz)
+
+Configuration values can not be changed after registration. To unregister
+the device, write a "0" to the "register" file. The configuration can be
+changed again after unregistering.
+
+To completely remove the device, simply rmdir the directory
+(/config/gpiommc/my_mmc in this example).
+There's no need to first unregister the device before removing it. That will
+be done automatically.
diff --git a/Documentation/spi/spi-summary b/Documentation/spi/spi-summary
index 4884cb3..7312ec1 100644
--- a/Documentation/spi/spi-summary
+++ b/Documentation/spi/spi-summary
@@ -1,7 +1,7 @@
 Overview of Linux kernel SPI support
 ====================================
 
-21-May-2007
+02-Feb-2012
 
 What is SPI?
 ------------
@@ -483,9 +483,9 @@
 and those methods.)
 
 After you initialize the spi_master, then use spi_register_master() to
-publish it to the rest of the system.  At that time, device nodes for
-the controller and any predeclared spi devices will be made available,
-and the driver model core will take care of binding them to drivers.
+publish it to the rest of the system. At that time, device nodes for the
+controller and any predeclared spi devices will be made available, and
+the driver model core will take care of binding them to drivers.
 
 If you need to remove your SPI controller driver, spi_unregister_master()
 will reverse the effect of spi_register_master().
@@ -521,21 +521,53 @@
 		** When you code setup(), ASSUME that the controller
 		** is actively processing transfers for another device.
 
-    master->transfer(struct spi_device *spi, struct spi_message *message)
-    	This must not sleep.  Its responsibility is arrange that the
-	transfer happens and its complete() callback is issued.  The two
-	will normally happen later, after other transfers complete, and
-	if the controller is idle it will need to be kickstarted.
-
     master->cleanup(struct spi_device *spi)
 	Your controller driver may use spi_device.controller_state to hold
 	state it dynamically associates with that device.  If you do that,
 	be sure to provide the cleanup() method to free that state.
 
+    master->prepare_transfer_hardware(struct spi_master *master)
+	This will be called by the queue mechanism to signal to the driver
+	that a message is coming in soon, so the subsystem requests the
+	driver to prepare the transfer hardware by issuing this call.
+	This may sleep.
+
+    master->unprepare_transfer_hardware(struct spi_master *master)
+	This will be called by the queue mechanism to signal to the driver
+	that there are no more messages pending in the queue and it may
+	relax the hardware (e.g. by power management calls). This may sleep.
+
+    master->transfer_one_message(struct spi_master *master,
+				 struct spi_message *mesg)
+	The subsystem calls the driver to transfer a single message while
+	queuing transfers that arrive in the meantime. When the driver is
+	finished with this message, it must call
+	spi_finalize_current_message() so the subsystem can issue the next
+	transfer. This may sleep.
+
+    DEPRECATED METHODS
+
+    master->transfer(struct spi_device *spi, struct spi_message *message)
+	This must not sleep. Its responsibility is arrange that the
+	transfer happens and its complete() callback is issued. The two
+	will normally happen later, after other transfers complete, and
+	if the controller is idle it will need to be kickstarted. This
+	method is not used on queued controllers and must be NULL if
+	transfer_one_message() and (un)prepare_transfer_hardware() are
+	implemented.
+
 
 SPI MESSAGE QUEUE
 
-The bulk of the driver will be managing the I/O queue fed by transfer().
+If you are happy with the standard queueing mechanism provided by the
+SPI subsystem, just implement the queued methods specified above. Using
+the message queue has the upside of centralizing a lot of code and
+providing pure process-context execution of methods. The message queue
+can also be elevated to realtime priority on high-priority SPI traffic.
+
+Unless the queueing mechanism in the SPI subsystem is selected, the bulk
+of the driver will be managing the I/O queue fed by the now deprecated
+function transfer().
 
 That queue could be purely conceptual.  For example, a driver used only
 for low-frequency sensor access might be fine using synchronous PIO.
@@ -561,4 +593,6 @@
 Mark Underwood
 Andrew Victor
 Vitaly Wool
-
+Grant Likely
+Mark Brown
+Linus Walleij
diff --git a/MAINTAINERS b/MAINTAINERS
index 9c63a43..c142bb1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3045,6 +3045,11 @@
 S:	Odd Fixes
 F:	drivers/tty/hvc/
 
+GPIOMMC DRIVER
+P:	Michael Buesch
+M:	mb@bu3sch.de
+S:	Maintained
+
 HARDWARE MONITORING
 M:	Jean Delvare <khali@linux-fr.org>
 M:	Guenter Roeck <guenter.roeck@ericsson.com>
@@ -4955,6 +4960,13 @@
 F:	include/scsi/osd_*
 F:	fs/exofs/
 
+OVERLAYFS FILESYSTEM
+M:	Miklos Szeredi <miklos@szeredi.hu>
+L:	linux-fsdevel@vger.kernel.org
+S:	Supported
+F:	fs/overlayfs/*
+F:	Documentation/filesystems/overlayfs.txt
+
 P54 WIRELESS DRIVER
 M:	Christian Lamparter <chunkeey@googlemail.com>
 L:	linux-wireless@vger.kernel.org
diff --git a/Makefile b/Makefile
index db96149..428b422 100644
--- a/Makefile
+++ b/Makefile
@@ -374,7 +374,7 @@
 KBUILD_AFLAGS   := -D__ASSEMBLY__
 KBUILD_AFLAGS_MODULE  := -DMODULE
 KBUILD_CFLAGS_MODULE  := -DMODULE
-KBUILD_LDFLAGS_MODULE := -T $(srctree)/scripts/module-common.lds
+KBUILD_LDFLAGS_MODULE = -T $(srctree)/scripts/module-common.lds $(if $(CONFIG_PROFILING),,-s)
 
 # Read KERNELRELEASE from include/config/kernel.release (if it exists)
 KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
@@ -559,9 +559,9 @@
 all: vmlinux
 
 ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
-KBUILD_CFLAGS	+= -Os
+KBUILD_CFLAGS	+= -Os -fno-caller-saves
 else
-KBUILD_CFLAGS	+= -O2
+KBUILD_CFLAGS	+= -O2 -fno-reorder-blocks -fno-tree-ch -fno-caller-saves
 endif
 
 include $(srctree)/arch/$(SRCARCH)/Makefile
@@ -620,6 +620,9 @@
 NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
 CHECKFLAGS     += $(NOSTDINC_FLAGS)
 
+# improve gcc optimization
+CFLAGS += $(call cc-option,-funit-at-a-time,)
+
 # warn about C99 declaration after statement
 KBUILD_CFLAGS += $(call cc-option,-Wdeclaration-after-statement,)
 
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index dedb885..ad09289 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -21,6 +21,7 @@
 	select HAVE_KERNEL_GZIP
 	select HAVE_KERNEL_LZO
 	select HAVE_KERNEL_LZMA
+	select HAVE_KERNEL_XZ
 	select HAVE_IRQ_WORK
 	select HAVE_PERF_EVENTS
 	select PERF_USE_VMALLOC
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index cf0a64c..2b8f093 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -92,6 +92,7 @@
 suffix_$(CONFIG_KERNEL_GZIP) = gzip
 suffix_$(CONFIG_KERNEL_LZO)  = lzo
 suffix_$(CONFIG_KERNEL_LZMA) = lzma
+suffix_$(CONFIG_KERNEL_XZ)   = xzkern
 
 # Borrowed libfdt files for the ATAG compatibility mode
 
@@ -115,7 +116,7 @@
 		 lib1funcs.o lib1funcs.S font.o font.c head.o misc.o $(OBJS)
 
 # Make sure files are removed during clean
-extra-y       += piggy.gzip piggy.lzo piggy.lzma lib1funcs.S $(libfdt) $(libfdt_hdrs)
+extra-y       += piggy.gzip piggy.lzo piggy.lzma piggy.xzkern lib1funcs.S ashldi3.S $(libfdt) $(libfdt_hdrs)
 
 ifeq ($(CONFIG_FUNCTION_TRACER),y)
 ORIG_CFLAGS := $(KBUILD_CFLAGS)
@@ -171,8 +172,14 @@
 	false; \
 fi
 
+# For __aeabi_llsl
+ashldi3 = $(obj)/ashldi3.o
+
+$(obj)/ashldi3.S: $(srctree)/arch/$(SRCARCH)/lib/ashldi3.S FORCE
+	$(call cmd,shipped)
+
 $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \
-	 	$(addprefix $(obj)/, $(OBJS)) $(lib1funcs) FORCE
+	 	$(addprefix $(obj)/, $(OBJS)) $(lib1funcs) $(ashldi3) FORCE
 	@$(check_for_multiple_zreladdr)
 	$(call if_changed,ld)
 	@$(check_for_bad_syms)
diff --git a/arch/arm/boot/compressed/decompress.c b/arch/arm/boot/compressed/decompress.c
index 07be5a2..f41b38c 100644
--- a/arch/arm/boot/compressed/decompress.c
+++ b/arch/arm/boot/compressed/decompress.c
@@ -44,6 +44,12 @@
 #include "../../../../lib/decompress_unlzma.c"
 #endif
 
+#ifdef CONFIG_KERNEL_XZ
+#define memmove memmove
+#define memcpy memcpy
+#include "../../../../lib/decompress_unxz.c"
+#endif
+
 int do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x))
 {
 	return decompress(input, len, NULL, NULL, output, NULL, error);
diff --git a/arch/arm/boot/compressed/piggy.xzkern.S b/arch/arm/boot/compressed/piggy.xzkern.S
new file mode 100644
index 0000000..5703f30
--- /dev/null
+++ b/arch/arm/boot/compressed/piggy.xzkern.S
@@ -0,0 +1,6 @@
+	.section .piggydata,#alloc
+	.globl	input_data
+input_data:
+	.incbin	"arch/arm/boot/compressed/piggy.xzkern"
+	.globl	input_data_end
+input_data_end:
diff --git a/arch/arm/include/asm/smp_twd.h b/arch/arm/include/asm/smp_twd.h
index ef9ffba9..3371e8f 100644
--- a/arch/arm/include/asm/smp_twd.h
+++ b/arch/arm/include/asm/smp_twd.h
@@ -18,11 +18,18 @@
 #define TWD_TIMER_CONTROL_PERIODIC	(1 << 1)
 #define TWD_TIMER_CONTROL_IT_ENABLE	(1 << 2)
 
+#define TWD_WDOG_CONTROL_ENABLE		(1 << 0)
+#define TWD_WDOG_CONTROL_PERIODIC	(1 << 1)
+#define TWD_WDOG_CONTROL_IT_ENABLE	(1 << 2)
+#define TWD_WDOG_CONTROL_TIMER_MODE	(0 << 3)
+#define TWD_WDOG_CONTROL_WATCHDOG_MODE	(1 << 3)
+
 struct clock_event_device;
 
 extern void __iomem *twd_base;
 
 void twd_timer_setup(struct clock_event_device *);
 void twd_timer_stop(struct clock_event_device *);
+unsigned long twd_timer_get_rate(void);
 
 #endif
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c
index 1e9be5d..4057690 100644
--- a/arch/arm/kernel/module.c
+++ b/arch/arm/kernel/module.c
@@ -81,6 +81,10 @@
 			return -ENOEXEC;
 		}
 
+		if ((IS_ERR_VALUE(sym->st_value) || !sym->st_value) &&
+		    ELF_ST_BIND(sym->st_info) == STB_WEAK)
+			continue;
+
 		loc = dstsec->sh_addr + rel->r_offset;
 
 		switch (ELF32_R_TYPE(rel->r_info)) {
diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c
index 7a79b24..f68de3e 100644
--- a/arch/arm/kernel/smp_twd.c
+++ b/arch/arm/kernel/smp_twd.c
@@ -268,3 +268,10 @@
 					0xf, 0xffffffff);
 	enable_percpu_irq(clk->irq, 0);
 }
+
+/* Needed by mpcore_wdt */
+unsigned long twd_timer_get_rate(void)
+{
+	return twd_timer_rate;
+}
+EXPORT_SYMBOL_GPL(twd_timer_get_rate);
diff --git a/arch/arm/mach-omap1/board-palmz71.c b/arch/arm/mach-omap1/board-palmz71.c
index e881945..b756b8d 100644
--- a/arch/arm/mach-omap1/board-palmz71.c
+++ b/arch/arm/mach-omap1/board-palmz71.c
@@ -291,8 +291,7 @@
 		}
 		gpio_direction_input(PALMZ71_USBDETECT_GPIO);
 		if (request_irq(gpio_to_irq(PALMZ71_USBDETECT_GPIO),
-				palmz71_powercable, IRQF_SAMPLE_RANDOM,
-				"palmz71-cable", 0))
+				palmz71_powercable, 0, "palmz71-cable", 0))
 			printk(KERN_ERR
 					"IRQ request for power cable failed!\n");
 		palmz71_powercable(gpio_to_irq(PALMZ71_USBDETECT_GPIO), 0);
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index 6ebd276..2b97823 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -455,7 +455,7 @@
 	init_timer(&mmc_timer);
 	mmc_timer.data = (unsigned long) data;
 	return request_irq(LUBBOCK_SD_IRQ, lubbock_detect_int,
-			IRQF_SAMPLE_RANDOM, "lubbock-sd-detect", data);
+			   0, "lubbock-sd-detect", data);
 }
 
 static int lubbock_mci_get_ro(struct device *dev)
diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c
index 3d6baf9..1508fa8 100644
--- a/arch/arm/mach-pxa/magician.c
+++ b/arch/arm/mach-pxa/magician.c
@@ -617,9 +617,8 @@
 static int magician_mci_init(struct device *dev,
 				irq_handler_t detect_irq, void *data)
 {
-	return request_irq(IRQ_MAGICIAN_SD, detect_irq,
-				IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
-				"mmc card detect", data);
+	return request_irq(IRQ_MAGICIAN_SD, detect_irq, IRQF_DISABLED,
+			   "mmc card detect", data);
 }
 
 static void magician_mci_exit(struct device *dev, void *data)
diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c
index 0f30af6..94f6b29 100644
--- a/arch/arm/mach-pxa/trizeps4.c
+++ b/arch/arm/mach-pxa/trizeps4.c
@@ -332,8 +332,8 @@
 	int err;
 
 	err = request_irq(TRIZEPS4_MMC_IRQ, mci_detect_int,
-		IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_SAMPLE_RANDOM,
-		"MMC card detect", data);
+			  IRQF_DISABLED | IRQF_TRIGGER_RISING,
+			  "MMC card detect", data);
 	if (err) {
 		printk(KERN_ERR "trizeps4_mci_init: MMC/SD: can't request"
 						"MMC card detect IRQ\n");
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index f9c9f33..ca2a1f4 100644
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -12,531 +12,3179 @@
 #
 #   http://www.arm.linux.org.uk/developer/machines/?action=new
 #
-# This is a cut-down version of the file; it contains only machines that
-# are merged into mainline or have been edited in the machine database
-# within the last 12 months.  References to machine_is_NAME() do not count!
-#
-# Last update: Tue Dec 6 11:07:38 2011
+# Last update: Fri Apr 20 08:30:36 2012
 #
 # machine_is_xxx	CONFIG_xxxx		MACH_TYPE_xxx		number
 #
 ebsa110			ARCH_EBSA110		EBSA110			0
 riscpc			ARCH_RPC		RISCPC			1
+nexuspci		ARCH_NEXUSPCI		NEXUSPCI		3
 ebsa285			ARCH_EBSA285		EBSA285			4
 netwinder		ARCH_NETWINDER		NETWINDER		5
 cats			ARCH_CATS		CATS			6
+tbox			ARCH_TBOX		TBOX			7
+co285			ARCH_CO285		CO285			8
+clps7110		ARCH_CLPS7110		CLPS7110		9
+archimedes		ARCH_ARC		ARCHIMEDES		10
+a5k			ARCH_A5K		A5K			11
+etoile			ARCH_ETOILE		ETOILE			12
+lacie_nas		ARCH_LACIE_NAS		LACIE_NAS		13
+clps7500		ARCH_CLPS7500		CLPS7500		14
 shark			ARCH_SHARK		SHARK			15
 brutus			SA1100_BRUTUS		BRUTUS			16
 personal_server		ARCH_PERSONAL_SERVER	PERSONAL_SERVER		17
+itsy			SA1100_ITSY		ITSY			18
 l7200			ARCH_L7200		L7200			19
 pleb			SA1100_PLEB		PLEB			20
 integrator		ARCH_INTEGRATOR		INTEGRATOR		21
 h3600			SA1100_H3600		H3600			22
+ixp1200			ARCH_IXP1200		IXP1200			23
 p720t			ARCH_P720T		P720T			24
 assabet			SA1100_ASSABET		ASSABET			25
+victor			SA1100_VICTOR		VICTOR			26
 lart			SA1100_LART		LART			27
+ranger			SA1100_RANGER		RANGER			28
 graphicsclient		SA1100_GRAPHICSCLIENT	GRAPHICSCLIENT		29
 xp860			SA1100_XP860		XP860			30
 cerf			SA1100_CERF		CERF			31
 nanoengine		SA1100_NANOENGINE	NANOENGINE		32
+fpic			SA1100_FPIC		FPIC			33
+extenex1		SA1100_EXTENEX1		EXTENEX1		34
+sherman			SA1100_SHERMAN		SHERMAN			35
+accelent_sa		SA1100_ACCELENT		ACCELENT_SA		36
+accelent_l7200		ARCH_L7200_ACCELENT	ACCELENT_L7200		37
+netport			SA1100_NETPORT		NETPORT			38
+pangolin		SA1100_PANGOLIN		PANGOLIN		39
+yopy			SA1100_YOPY		YOPY			40
+coolidge		SA1100_COOLIDGE		COOLIDGE		41
+huw_webpanel		SA1100_HUW_WEBPANEL	HUW_WEBPANEL		42
+spotme			ARCH_SPOTME		SPOTME			43
+freebird		ARCH_FREEBIRD		FREEBIRD		44
+ti925			ARCH_TI925		TI925			45
+riscstation		ARCH_RISCSTATION	RISCSTATION		46
+cavy			SA1100_CAVY		CAVY			47
 jornada720		SA1100_JORNADA720	JORNADA720		48
+omnimeter		SA1100_OMNIMETER	OMNIMETER		49
 edb7211			ARCH_EDB7211		EDB7211			50
+citygo			SA1100_CITYGO		CITYGO			51
 pfs168			SA1100_PFS168		PFS168			52
+spot			SA1100_SPOT		SPOT			53
 flexanet		SA1100_FLEXANET		FLEXANET		54
+webpal			ARCH_WEBPAL		WEBPAL			55
+linpda			SA1100_LINPDA		LINPDA			56
+anakin			ARCH_ANAKIN		ANAKIN			57
+mvi			SA1100_MVI		MVI			58
+jupiter			SA1100_JUPITER		JUPITER			59
+psionw			ARCH_PSIONW		PSIONW			60
+aln			SA1100_ALN		ALN			61
+epxa			ARCH_CAMELOT		CAMELOT			62
+gds2200			SA1100_GDS2200		GDS2200			63
+netbook			SA1100_PSION_SERIES7	PSION_SERIES7		64
+xfile			SA1100_XFILE		XFILE			65
+accelent_ep9312		ARCH_ACCELENT_EP9312	ACCELENT_EP9312		66
+ic200			ARCH_IC200		IC200			67
+creditlart		SA1100_CREDITLART	CREDITLART		68
+htm			SA1100_HTM		HTM			69
+iq80310			ARCH_IQ80310		IQ80310			70
+freebot			SA1100_FREEBOT		FREEBOT			71
+entel			ARCH_ENTEL		ENTEL			72
+enp3510			ARCH_ENP3510		ENP3510			73
+trizeps			SA1100_TRIZEPS		TRIZEPS			74
+nesa			SA1100_NESA		NESA			75
+venus			ARCH_VENUS		VENUS			76
+tardis			ARCH_TARDIS		TARDIS			77
+mercury			ARCH_MERCURY		MERCURY			78
+empeg			SA1100_EMPEG		EMPEG			79
+adi_evb			ARCH_I80200FCC		I80200FCC		80
+itt_cpb			SA1100_ITT_CPB		ITT_CPB			81
+svc			SA1100_SVC		SVC			82
+alpha2			SA1100_ALPHA2		ALPHA2			84
+alpha1			SA1100_ALPHA1		ALPHA1			85
+netarm			ARCH_NETARM		NETARM			86
 simpad			SA1100_SIMPAD		SIMPAD			87
+pda1			ARCH_PDA1		PDA1			88
 lubbock			ARCH_LUBBOCK		LUBBOCK			89
+aniko			ARCH_ANIKO		ANIKO			90
 clep7212		ARCH_CLEP7212		CLEP7212		91
+cs89712			ARCH_CS89712		CS89712			92
+weararm			SA1100_WEARARM		WEARARM			93
+possio_px		SA1100_POSSIO_PX	POSSIO_PX		94
+sidearm			SA1100_SIDEARM		SIDEARM			95
+stork			SA1100_STORK		STORK			96
 shannon			SA1100_SHANNON		SHANNON			97
+ace			ARCH_ACE		ACE			98
+ballyarm		SA1100_BALLYARM		BALLYARM		99
+simputer		SA1100_SIMPUTER		SIMPUTER		100
+nexterm			SA1100_NEXTERM		NEXTERM			101
+sa1100_elf		SA1100_SA1100_ELF	SA1100_ELF		102
+gator			SA1100_GATOR		GATOR			103
+granite			ARCH_GRANITE		GRANITE			104
 consus			SA1100_CONSUS		CONSUS			105
 aaed2000		ARCH_AAED2000		AAED2000		106
 cdb89712		ARCH_CDB89712		CDB89712		107
 graphicsmaster		SA1100_GRAPHICSMASTER	GRAPHICSMASTER		108
 adsbitsy		SA1100_ADSBITSY		ADSBITSY		109
 pxa_idp			ARCH_PXA_IDP		PXA_IDP			110
+plce			ARCH_PLCE		PLCE			111
 pt_system3		SA1100_PT_SYSTEM3	PT_SYSTEM3		112
+murphy			ARCH_MEDALB		MEDALB			113
+eagle			ARCH_EAGLE		EAGLE			114
+dsc21			ARCH_DSC21		DSC21			115
+dsc24			ARCH_DSC24		DSC24			116
+ti5472			ARCH_TI5472		TI5472			117
 autcpu12		ARCH_AUTCPU12		AUTCPU12		118
+uengine			ARCH_UENGINE		UENGINE			119
+bluestem		SA1100_BLUESTEM		BLUESTEM		120
+xingu8			ARCH_XINGU8		XINGU8			121
+bushstb			ARCH_BUSHSTB		BUSHSTB			122
+epsilon1		SA1100_EPSILON1		EPSILON1		123
+balloon			SA1100_BALLOON		BALLOON			124
+puppy			ARCH_PUPPY		PUPPY			125
+elroy			SA1100_ELROY		ELROY			126
+gms720			ARCH_GMS720		GMS720			127
+s24x			ARCH_S24X		S24X			128
+jtel_clep7312		ARCH_JTEL_CLEP7312	JTEL_CLEP7312		129
+cx821xx			ARCH_CX821XX		CX821XX			130
+edb7312			ARCH_EDB7312		EDB7312			131
+bsa1110			SA1100_BSA1110		BSA1110			132
+powerpin		ARCH_POWERPIN		POWERPIN		133
+openarm			ARCH_OPENARM		OPENARM			134
+whitechapel		SA1100_WHITECHAPEL	WHITECHAPEL		135
 h3100			SA1100_H3100		H3100			136
+h3800			SA1100_H3800		H3800			137
+blue_v1			ARCH_BLUE_V1		BLUE_V1			138
+pxa_cerf		ARCH_PXA_CERF		PXA_CERF		139
+arm7tevb		ARCH_ARM7TEVB		ARM7TEVB		140
+d7400			SA1100_D7400		D7400			141
+piranha			ARCH_PIRANHA		PIRANHA			142
+sbcamelot		SA1100_SBCAMELOT	SBCAMELOT		143
+kings			SA1100_KINGS		KINGS			144
+smdk2400		ARCH_SMDK2400		SMDK2400		145
 collie			SA1100_COLLIE		COLLIE			146
+idr			ARCH_IDR		IDR			147
 badge4			SA1100_BADGE4		BADGE4			148
+webnet			ARCH_WEBNET		WEBNET			149
+d7300			SA1100_D7300		D7300			150
+cep			SA1100_CEP		CEP			151
 fortunet		ARCH_FORTUNET		FORTUNET		152
+vc547x			ARCH_VC547X		VC547X			153
+filewalker		SA1100_FILEWALKER	FILEWALKER		154
+netgateway		SA1100_NETGATEWAY	NETGATEWAY		155
+symbol2800		SA1100_SYMBOL2800	SYMBOL2800		156
+suns			SA1100_SUNS		SUNS			157
+frodo			SA1100_FRODO		FRODO			158
+ms301			SA1100_MACH_TYTE_MS301	MACH_TYTE_MS301		159
 mx1ads			ARCH_MX1ADS		MX1ADS			160
 h7201			ARCH_H7201		H7201			161
 h7202			ARCH_H7202		H7202			162
+amico			ARCH_AMICO		AMICO			163
+iam			SA1100_IAM		IAM			164
+tt530			SA1100_TT530		TT530			165
+sam2400			ARCH_SAM2400		SAM2400			166
+jornada56x		SA1100_JORNADA56X	JORNADA56X		167
+active			SA1100_ACTIVE		ACTIVE			168
 iq80321			ARCH_IQ80321		IQ80321			169
+wid			SA1100_WID		WID			170
+sabinal			ARCH_SABINAL		SABINAL			171
+ixp425_matacumbe	ARCH_IXP425_MATACUMBE	IXP425_MATACUMBE	172
+miniprint		SA1100_MINIPRINT	MINIPRINT		173
+adm510x			ARCH_ADM510X		ADM510X			174
+svs200			SA1100_SVS200		SVS200			175
+atg_tcu			ARCH_ATG_TCU		ATG_TCU			176
+jornada820		SA1100_JORNADA820	JORNADA820		177
+s3c44b0			ARCH_S3C44B0		S3C44B0			178
+margis2			ARCH_MARGIS2		MARGIS2			179
 ks8695			ARCH_KS8695		KS8695			180
+brh			ARCH_BRH		BRH			181
+s3c2410			ARCH_S3C2410		S3C2410			182
+possio_px30		ARCH_POSSIO_PX30	POSSIO_PX30		183
+s3c2800			ARCH_S3C2800		S3C2800			184
+fleetwood		SA1100_FLEETWOOD	FLEETWOOD		185
+omaha			ARCH_OMAHA		OMAHA			186
+ta7			ARCH_TA7		TA7			187
+nova			SA1100_NOVA		NOVA			188
+hmk			ARCH_HMK		HMK			189
 karo			ARCH_KARO		KARO			190
+fester			SA1100_FESTER		FESTER			191
+gpi			ARCH_GPI		GPI			192
 smdk2410		ARCH_SMDK2410		SMDK2410		193
+i519			ARCH_I519		I519			194
+nexio			SA1100_NEXIO		NEXIO			195
+bitbox			SA1100_BITBOX		BITBOX			196
+g200			SA1100_G200		G200			197
+gill			SA1100_GILL		GILL			198
+pxa_mercury		ARCH_PXA_MERCURY	PXA_MERCURY		199
 ceiva			ARCH_CEIVA		CEIVA			200
+fret			SA1100_FRET		FRET			201
+emailphone		SA1100_EMAILPHONE	EMAILPHONE		202
+h3900			ARCH_H3900		H3900			203
+pxa1			ARCH_PXA1		PXA1			204
+koan369			SA1100_KOAN369		KOAN369			205
+cogent			ARCH_COGENT		COGENT			206
+esl_simputer		ARCH_ESL_SIMPUTER	ESL_SIMPUTER		207
+esl_simputer_clr	ARCH_ESL_SIMPUTER_CLR	ESL_SIMPUTER_CLR	208
+esl_simputer_bw		ARCH_ESL_SIMPUTER_BW	ESL_SIMPUTER_BW		209
+hhp_cradle		ARCH_HHP_CRADLE		HHP_CRADLE		210
+he500			ARCH_HE500		HE500			211
+inhandelf2		SA1100_INHANDELF2	INHANDELF2		212
+inhandftip		SA1100_INHANDFTIP	INHANDFTIP		213
+dnp1110			SA1100_DNP1110		DNP1110			214
+pnp1110			SA1100_PNP1110		PNP1110			215
+csb226			ARCH_CSB226		CSB226			216
+arnold			SA1100_ARNOLD		ARNOLD			217
 voiceblue		MACH_VOICEBLUE		VOICEBLUE		218
+jz8028			ARCH_JZ8028		JZ8028			219
 h5400			ARCH_H5400		H5400			220
+forte			SA1100_FORTE		FORTE			221
+acam			SA1100_ACAM		ACAM			222
+abox			SA1100_ABOX		ABOX			223
+atmel			ARCH_ATMEL		ATMEL			224
+sitsang			ARCH_SITSANG		SITSANG			225
+cpu1110lcdnet		SA1100_CPU1110LCDNET	CPU1110LCDNET		226
+mpl_vcma9		ARCH_MPL_VCMA9		MPL_VCMA9		227
+opus_a1			ARCH_OPUS_A1		OPUS_A1			228
+daytona			ARCH_DAYTONA		DAYTONA			229
+killbear		SA1100_KILLBEAR		KILLBEAR		230
+yoho			ARCH_YOHO		YOHO			231
+jasper			ARCH_JASPER		JASPER			232
+dsc25			ARCH_DSC25		DSC25			233
 omap_innovator		MACH_OMAP_INNOVATOR	OMAP_INNOVATOR		234
+mnci			ARCH_RAMSES		RAMSES			235
+s28x			ARCH_S28X		S28X			236
+mport3			ARCH_MPORT3		MPORT3			237
+pxa_eagle250		ARCH_PXA_EAGLE250	PXA_EAGLE250		238
+pdb			ARCH_PDB		PDB			239
+blue_2g			SA1100_BLUE_2G		BLUE_2G			240
+bluearch		SA1100_BLUEARCH		BLUEARCH		241
 ixdp2400		ARCH_IXDP2400		IXDP2400		242
 ixdp2800		ARCH_IXDP2800		IXDP2800		243
+explorer		SA1100_EXPLORER		EXPLORER		244
 ixdp425			ARCH_IXDP425		IXDP425			245
+chimp			ARCH_CHIMP		CHIMP			246
+stork_nest		ARCH_STORK_NEST		STORK_NEST		247
+stork_egg		ARCH_STORK_EGG		STORK_EGG		248
+wismo			SA1100_WISMO		WISMO			249
+ezlinx			ARCH_EZLINX		EZLINX			250
+at91rm9200		ARCH_AT91RM9200		AT91RM9200		251
+adtech_orion		ARCH_ADTECH_ORION	ADTECH_ORION		252
+neptune			ARCH_NEPTUNE		NEPTUNE			253
 hackkit			SA1100_HACKKIT		HACKKIT			254
+pxa_wins30		ARCH_PXA_WINS30		PXA_WINS30		255
+lavinna			SA1100_LAVINNA		LAVINNA			256
+pxa_uengine		ARCH_PXA_UENGINE	PXA_UENGINE		257
+innokom			ARCH_INNOKOM		INNOKOM			258
+bms			ARCH_BMS		BMS			259
 ixcdp1100		ARCH_IXCDP1100		IXCDP1100		260
+prpmc1100		ARCH_PRPMC1100		PRPMC1100		261
 at91rm9200dk		ARCH_AT91RM9200DK	AT91RM9200DK		262
+armstick		ARCH_ARMSTICK		ARMSTICK		263
+armonie			ARCH_ARMONIE		ARMONIE			264
+mport1			ARCH_MPORT1		MPORT1			265
+s3c5410			ARCH_S3C5410		S3C5410			266
+zcp320a			ARCH_ZCP320A		ZCP320A			267
+i_box			ARCH_I_BOX		I_BOX			268
+stlc1502		ARCH_STLC1502		STLC1502		269
+siren			ARCH_SIREN		SIREN			270
+greenlake		ARCH_GREENLAKE		GREENLAKE		271
+argus			ARCH_ARGUS		ARGUS			272
+combadge		SA1100_COMBADGE		COMBADGE		273
+rokepxa			ARCH_ROKEPXA		ROKEPXA			274
 cintegrator		ARCH_CINTEGRATOR	CINTEGRATOR		275
+guidea07		ARCH_GUIDEA07		GUIDEA07		276
+tat257			ARCH_TAT257		TAT257			277
+igp2425			ARCH_IGP2425		IGP2425			278
+bluegrama		ARCH_BLUEGRAMMA		BLUEGRAMMA		279
+ipod			ARCH_IPOD		IPOD			280
+adsbitsyx		ARCH_ADSBITSYX		ADSBITSYX		281
+trizeps2		ARCH_TRIZEPS2		TRIZEPS2		282
 viper			ARCH_VIPER		VIPER			283
+adsbitsyplus		SA1100_ADSBITSYPLUS	ADSBITSYPLUS		284
+adsagc			SA1100_ADSAGC		ADSAGC			285
+stp7312			ARCH_STP7312		STP7312			286
+nx_phnx			MACH_NX_PHNX		NX_PHNX			287
+wep_ep250		ARCH_WEP_EP250		WEP_EP250		288
+inhandelf3		ARCH_INHANDELF3		INHANDELF3		289
 adi_coyote		ARCH_ADI_COYOTE		ADI_COYOTE		290
+iyonix			ARCH_IYONIX		IYONIX			291
+damicam1		ARCH_DAMICAM_SA1110	DAMICAM_SA1110		292
+meg03			ARCH_MEG03		MEG03			293
+pxa_whitechapel		ARCH_PXA_WHITECHAPEL	PXA_WHITECHAPEL		294
+nwsc			ARCH_NWSC		NWSC			295
+nwlarm			ARCH_NWLARM		NWLARM			296
+ixp425_mguard		ARCH_IXP425_MGUARD	IXP425_MGUARD		297
+pxa_netdcu4		ARCH_PXA_NETDCU4	PXA_NETDCU4		298
 ixdp2401		ARCH_IXDP2401		IXDP2401		299
 ixdp2801		ARCH_IXDP2801		IXDP2801		300
+zodiac			ARCH_ZODIAC		ZODIAC			301
+armmodul		ARCH_ARMMODUL		ARMMODUL		302
+ketop			SA1100_KETOP		KETOP			303
+av7200			ARCH_AV7200		AV7200			304
+arch_ti925		ARCH_ARCH_TI925		ARCH_TI925		305
+acq200			ARCH_ACQ200		ACQ200			306
+pt_dafit		SA1100_PT_DAFIT		PT_DAFIT		307
+ihba			ARCH_IHBA		IHBA			308
+quinque			ARCH_QUINQUE		QUINQUE			309
+nimbraone		ARCH_NIMBRAONE		NIMBRAONE		310
+nimbra29x		ARCH_NIMBRA29X		NIMBRA29X		311
+nimbra210		ARCH_NIMBRA210		NIMBRA210		312
+hhp_d95xx		ARCH_HHP_D95XX		HHP_D95XX		313
+labarm			ARCH_LABARM		LABARM			314
+m825xx			ARCH_M825XX		M825XX			315
+m7100			SA1100_M7100		M7100			316
+nipc2			ARCH_NIPC2		NIPC2			317
+fu7202			ARCH_FU7202		FU7202			318
+adsagx			ARCH_ADSAGX		ADSAGX			319
+pxa_pooh		ARCH_PXA_POOH		PXA_POOH		320
+bandon			ARCH_BANDON		BANDON			321
+pcm7210			ARCH_PCM7210		PCM7210			322
+nms9200			ARCH_NMS9200		NMS9200			323
+logodl			ARCH_LOGODL		LOGODL			324
+m7140			SA1100_M7140		M7140			325
+korebot			ARCH_KOREBOT		KOREBOT			326
 iq31244			ARCH_IQ31244		IQ31244			327
+koan393			SA1100_KOAN393		KOAN393			328
+inhandftip3		ARCH_INHANDFTIP3	INHANDFTIP3		329
+gonzo			ARCH_GONZO		GONZO			330
 bast			ARCH_BAST		BAST			331
+scanpass		ARCH_SCANPASS		SCANPASS		332
+ep7312_pooh		ARCH_EP7312_POOH	EP7312_POOH		333
+ta7s			ARCH_TA7S		TA7S			334
+ta7v			ARCH_TA7V		TA7V			335
+icarus			SA1100_ICARUS		ICARUS			336
+h1900			ARCH_H1900		H1900			337
+gemini			SA1100_GEMINI		GEMINI			338
+axim			ARCH_AXIM		AXIM			339
+audiotron		ARCH_AUDIOTRON		AUDIOTRON		340
+h2200			ARCH_H2200		H2200			341
+loox600			ARCH_LOOX600		LOOX600			342
+niop			ARCH_NIOP		NIOP			343
+dm310			ARCH_DM310		DM310			344
+seedpxa_c2		ARCH_SEEDPXA_C2		SEEDPXA_C2		345
+ixp4xx_mguardpci	ARCH_IXP4XX_MGUARD_PCI	IXP4XX_MGUARD_PCI	346
 h1940			ARCH_H1940		H1940			347
+scorpio			ARCH_SCORPIO		SCORPIO			348
+viva			ARCH_VIVA		VIVA			349
+pxa_xcard		ARCH_PXA_XCARD		PXA_XCARD		350
+csb335			ARCH_CSB335		CSB335			351
+ixrd425			ARCH_IXRD425		IXRD425			352
+iq80315			ARCH_IQ80315		IQ80315			353
+nmp7312			ARCH_NMP7312		NMP7312			354
+cx861xx			ARCH_CX861XX		CX861XX			355
 enp2611			ARCH_ENP2611		ENP2611			356
+xda			SA1100_XDA		XDA			357
+csir_ims		ARCH_CSIR_IMS		CSIR_IMS		358
+ixp421_dnaeeth		ARCH_IXP421_DNAEETH	IXP421_DNAEETH		359
+pocketserv9200		ARCH_POCKETSERV9200	POCKETSERV9200		360
+toto			ARCH_TOTO		TOTO			361
 s3c2440			ARCH_S3C2440		S3C2440			362
+ks8695p			ARCH_KS8695P		KS8695P			363
+se4000			ARCH_SE4000		SE4000			364
+quadriceps		ARCH_QUADRICEPS		QUADRICEPS		365
+bronco			ARCH_BRONCO		BRONCO			366
+esl_wireless_tab	ARCH_ESL_WIRELESS_TAB	ESL_WIRELESS_TAB	367
+esl_sofcomp		ARCH_ESL_SOFCOMP	ESL_SOFCOMP		368
+s5c7375			ARCH_S5C7375		S5C7375			369
+spearhead		ARCH_SPEARHEAD		SPEARHEAD		370
+pantera			ARCH_PANTERA		PANTERA			371
+prayoglite		ARCH_PRAYOGLITE		PRAYOGLITE		372
 gumstix			ARCH_GUMSTIX		GUMSTIX			373
+rcube			ARCH_RCUBE		RCUBE			374
+rea_olv			ARCH_REA_OLV		REA_OLV			375
+pxa_iphone		ARCH_PXA_IPHONE		PXA_IPHONE		376
+s3c3410			ARCH_S3C3410		S3C3410			377
+espd_4510b		ARCH_ESPD_4510B		ESPD_4510B		378
+mp1x			ARCH_MP1X		MP1X			379
+at91rm9200tb		ARCH_AT91RM9200TB	AT91RM9200TB		380
+adsvgx			ARCH_ADSVGX		ADSVGX			381
 omap_h2			MACH_OMAP_H2		OMAP_H2			382
+pelee			ARCH_PELEE		PELEE			383
 e740			MACH_E740		E740			384
 iq80331			ARCH_IQ80331		IQ80331			385
 versatile_pb		ARCH_VERSATILE_PB	VERSATILE_PB		387
 kev7a400		MACH_KEV7A400		KEV7A400		388
 lpd7a400		MACH_LPD7A400		LPD7A400		389
 lpd7a404		MACH_LPD7A404		LPD7A404		390
+fujitsu_camelot		ARCH_FUJITSU_CAMELOT	FUJITSU_CAMELOT		391
+janus2m			ARCH_JANUS2M		JANUS2M			392
+embtf			MACH_EMBTF		EMBTF			393
+hpm			MACH_HPM		HPM			394
+smdk2410tk		MACH_SMDK2410TK		SMDK2410TK		395
+smdk2410aj		MACH_SMDK2410AJ		SMDK2410AJ		396
+streetracer		MACH_STREETRACER	STREETRACER		397
+eframe			MACH_EFRAME		EFRAME			398
 csb337			MACH_CSB337		CSB337			399
+pxa_lark		MACH_PXA_LARK		PXA_LARK		400
+pxa_pnp2110		MACH_PNP2110		PNP2110			401
+tcc72x			MACH_TCC72X		TCC72X			402
+altair			MACH_ALTAIR		ALTAIR			403
+kc3			MACH_KC3		KC3			404
+sinteftd		MACH_SINTEFTD		SINTEFTD		405
 mainstone		MACH_MAINSTONE		MAINSTONE		406
+aday4x			MACH_ADAY4X		ADAY4X			407
+lite300			MACH_LITE300		LITE300			408
+s5c7376			MACH_S5C7376		S5C7376			409
+mt02			MACH_MT02		MT02			410
+mport3s			MACH_MPORT3S		MPORT3S			411
+ra_alpha		MACH_RA_ALPHA		RA_ALPHA		412
 xcep			MACH_XCEP		XCEP			413
 arcom_vulcan		MACH_ARCOM_VULCAN	ARCOM_VULCAN		414
+stargate		MACH_STARGATE		STARGATE		415
+armadilloj		MACH_ARMADILLOJ		ARMADILLOJ		416
+elroy_jack		MACH_ELROY_JACK		ELROY_JACK		417
+backend			MACH_BACKEND		BACKEND			418
+s5linbox		MACH_S5LINBOX		S5LINBOX		419
 nomadik			MACH_NOMADIK		NOMADIK			420
+ia_cpu_9200		MACH_IA_CPU_9200	IA_CPU_9200		421
+at91_bja1		MACH_AT91_BJA1		AT91_BJA1		422
 corgi			MACH_CORGI		CORGI			423
 poodle			MACH_POODLE		POODLE			424
+ten			MACH_TEN		TEN			425
+roverp5p		MACH_ROVERP5P		ROVERP5P		426
+sc2700			MACH_SC2700		SC2700			427
+ex_eagle		MACH_EX_EAGLE		EX_EAGLE		428
+nx_pxa12		MACH_NX_PXA12		NX_PXA12		429
+nx_pxa5			MACH_NX_PXA5		NX_PXA5			430
+blackboard2		MACH_BLACKBOARD2	BLACKBOARD2		431
+i819			MACH_I819		I819			432
+ixmb995e		MACH_IXMB995E		IXMB995E		433
+skyrider		MACH_SKYRIDER		SKYRIDER		434
+skyhawk			MACH_SKYHAWK		SKYHAWK			435
+enterprise		MACH_ENTERPRISE		ENTERPRISE		436
+dep2410			MACH_DEP2410		DEP2410			437
 armcore			MACH_ARMCORE		ARMCORE			438
+hobbit			MACH_HOBBIT		HOBBIT			439
+h7210			MACH_H7210		H7210			440
+pxa_netdcu5		MACH_PXA_NETDCU5	PXA_NETDCU5		441
+acc			MACH_ACC		ACC			442
+esl_sarva		MACH_ESL_SARVA		ESL_SARVA		443
+xm250			MACH_XM250		XM250			444
+t6tc1xb			MACH_T6TC1XB		T6TC1XB			445
+ess710			MACH_ESS710		ESS710			446
 mx31ads			MACH_MX31ADS		MX31ADS			447
 himalaya		MACH_HIMALAYA		HIMALAYA		448
+bolfenk			MACH_BOLFENK		BOLFENK			449
+at91rm9200kr		MACH_AT91RM9200KR	AT91RM9200KR		450
 edb9312			MACH_EDB9312		EDB9312			451
 omap_generic		MACH_OMAP_GENERIC	OMAP_GENERIC		452
+aximx3			MACH_AXIMX3		AXIMX3			453
+eb67xdip		MACH_EB67XDIP		EB67XDIP		454
+webtxs			MACH_WEBTXS		WEBTXS			455
+hawk			MACH_HAWK		HAWK			456
+ccat91sbc001		MACH_CCAT91SBC001	CCAT91SBC001		457
+expresso		MACH_EXPRESSO		EXPRESSO		458
+h4000			MACH_H4000		H4000			459
+dino			MACH_DINO		DINO			460
+ml675k			MACH_ML675K		ML675K			461
 edb9301			MACH_EDB9301		EDB9301			462
 edb9315			MACH_EDB9315		EDB9315			463
+reciva_tt		MACH_RECIVA_TT		RECIVA_TT		464
+cstcb01			MACH_CSTCB01		CSTCB01			465
+cstcb1			MACH_CSTCB1		CSTCB1			466
+shadwell		MACH_SHADWELL		SHADWELL		467
+goepel263		MACH_GOEPEL263		GOEPEL263		468
+acq100			MACH_ACQ100		ACQ100			469
+mx1fs2			MACH_MX1FS2		MX1FS2			470
+hiptop_g1		MACH_HIPTOP_G1		HIPTOP_G1		471
+sparky			MACH_SPARKY		SPARKY			472
+ns9750			MACH_NS9750		NS9750			473
+phoenix			MACH_PHOENIX		PHOENIX			474
 vr1000			MACH_VR1000		VR1000			475
+deisterpxa		MACH_DEISTERPXA		DEISTERPXA		476
+bcm1160			MACH_BCM1160		BCM1160			477
+pcm022			MACH_PCM022		PCM022			478
+adsgcx			MACH_ADSGCX		ADSGCX			479
+dreadnaught		MACH_DREADNAUGHT	DREADNAUGHT		480
+dm320			MACH_DM320		DM320			481
+markov			MACH_MARKOV		MARKOV			482
+cos7a400		MACH_COS7A400		COS7A400		483
+milano			MACH_MILANO		MILANO			484
+ue9328			MACH_UE9328		UE9328			485
+uex255			MACH_UEX255		UEX255			486
+ue2410			MACH_UE2410		UE2410			487
+a620			MACH_A620		A620			488
+ocelot			MACH_OCELOT		OCELOT			489
+cheetah			MACH_CHEETAH		CHEETAH			490
 omap_perseus2		MACH_OMAP_PERSEUS2	OMAP_PERSEUS2		491
+zvue			MACH_ZVUE		ZVUE			492
+roverp1			MACH_ROVERP1		ROVERP1			493
+asidial2		MACH_ASIDIAL2		ASIDIAL2		494
+s3c24a0			MACH_S3C24A0		S3C24A0			495
 e800			MACH_E800		E800			496
 e750			MACH_E750		E750			497
+s3c5500			MACH_S3C5500		S3C5500			498
+smdk5500		MACH_SMDK5500		SMDK5500		499
+signalsync		MACH_SIGNALSYNC		SIGNALSYNC		500
+nbc			MACH_NBC		NBC			501
+kodiak			MACH_KODIAK		KODIAK			502
+netbookpro		MACH_NETBOOKPRO		NETBOOKPRO		503
+hw90200			MACH_HW90200		HW90200			504
+condor			MACH_CONDOR		CONDOR			505
+cup			MACH_CUP		CUP			506
+kite			MACH_KITE		KITE			507
 scb9328			MACH_SCB9328		SCB9328			508
 omap_h3			MACH_OMAP_H3		OMAP_H3			509
 omap_h4			MACH_OMAP_H4		OMAP_H4			510
+n10			MACH_N10		N10			511
+montejade		MACH_MONTAJADE		MONTAJADE		512
+sg560			MACH_SG560		SG560			513
+dp1000			MACH_DP1000		DP1000			514
 omap_osk		MACH_OMAP_OSK		OMAP_OSK		515
+rg100v3			MACH_RG100V3		RG100V3			516
+mx2ads			MACH_MX2ADS		MX2ADS			517
+pxa_kilo		MACH_PXA_KILO		PXA_KILO		518
+ixp4xx_eagle		MACH_IXP4XX_EAGLE	IXP4XX_EAGLE		519
 tosa			MACH_TOSA		TOSA			520
+mb2520f			MACH_MB2520F		MB2520F			521
+emc1000			MACH_EMC1000		EMC1000			522
+tidsc25			MACH_TIDSC25		TIDSC25			523
+akcpmxl			MACH_AKCPMXL		AKCPMXL			524
+av3xx			MACH_AV3XX		AV3XX			525
 avila			MACH_AVILA		AVILA			526
+pxa_mpm10		MACH_PXA_MPM10		PXA_MPM10		527
+pxa_kyanite		MACH_PXA_KYANITE	PXA_KYANITE		528
+sgold			MACH_SGOLD		SGOLD			529
+oscar			MACH_OSCAR		OSCAR			530
+epxa4usb2		MACH_EPXA4USB2		EPXA4USB2		531
+xsengine		MACH_XSENGINE		XSENGINE		532
+ip600			MACH_IP600		IP600			533
+mcan2			MACH_MCAN2		MCAN2			534
+ddi_blueridge		MACH_DDI_BLUERIDGE	DDI_BLUERIDGE		535
+skyminder		MACH_SKYMINDER		SKYMINDER		536
+lpd79520		MACH_LPD79520		LPD79520		537
 edb9302			MACH_EDB9302		EDB9302			538
+hw90340			MACH_HW90340		HW90340			539
+cip_box			MACH_CIP_BOX		CIP_BOX			540
+ivpn			MACH_IVPN		IVPN			541
+rsoc2			MACH_RSOC2		RSOC2			542
 husky			MACH_HUSKY		HUSKY			543
+boxer			MACH_BOXER		BOXER			544
 shepherd		MACH_SHEPHERD		SHEPHERD		545
+aml42800aa		MACH_AML42800AA		AML42800AA		546
+lpc2294			MACH_LPC2294		LPC2294			548
+switchgrass		MACH_SWITCHGRASS	SWITCHGRASS		549
+ens_cmu			MACH_ENS_CMU		ENS_CMU			550
+mm6_sdb			MACH_MM6_SDB		MM6_SDB			551
+saturn			MACH_SATURN		SATURN			552
+i30030evb		MACH_I30030EVB		I30030EVB		553
+mxc27530evb		MACH_MXC27530EVB	MXC27530EVB		554
+smdk2800		MACH_SMDK2800		SMDK2800		555
+mtwilson		MACH_MTWILSON		MTWILSON		556
+ziti			MACH_ZITI		ZITI			557
+grandfather		MACH_GRANDFATHER	GRANDFATHER		558
+tengine			MACH_TENGINE		TENGINE			559
+s3c2460			MACH_S3C2460		S3C2460			560
+pdm			MACH_PDM		PDM			561
 h4700			MACH_H4700		H4700			562
+h6300			MACH_H6300		H6300			563
+rz1700			MACH_RZ1700		RZ1700			564
+a716			MACH_A716		A716			565
+estk2440a		MACH_ESTK2440A		ESTK2440A		566
+atwixp425		MACH_ATWIXP425		ATWIXP425		567
+csb336			MACH_CSB336		CSB336			568
+rirm2			MACH_RIRM2		RIRM2			569
+cx23518			MACH_CX23518		CX23518			570
+cx2351x			MACH_CX2351X		CX2351X			571
+computime		MACH_COMPUTIME		COMPUTIME		572
+izarus			MACH_IZARUS		IZARUS			573
+pxa_rts			MACH_RTS		RTS			574
+se5100			MACH_SE5100		SE5100			575
+s3c2510			MACH_S3C2510		S3C2510			576
+csb437tl		MACH_CSB437TL		CSB437TL		577
+slauson			MACH_SLAUSON		SLAUSON			578
+pearlriver		MACH_PEARLRIVER		PEARLRIVER		579
+tdc_p210		MACH_TDC_P210		TDC_P210		580
+sg580			MACH_SG580		SG580			581
+wrsbcarm7		MACH_WRSBCARM7		WRSBCARM7		582
+ipd			MACH_IPD		IPD			583
+pxa_dnp2110		MACH_PXA_DNP2110	PXA_DNP2110		584
+xaeniax			MACH_XAENIAX		XAENIAX			585
+somn4250		MACH_SOMN4250		SOMN4250		586
+pleb2			MACH_PLEB2		PLEB2			587
+cornwallis		MACH_CORNWALLIS		CORNWALLIS		588
+gurney_drv		MACH_GURNEY_DRV		GURNEY_DRV		589
+chaffee			MACH_CHAFFEE		CHAFFEE			590
+rms101			MACH_RMS101		RMS101			591
 rx3715			MACH_RX3715		RX3715			592
+swift			MACH_SWIFT		SWIFT			593
+roverp7			MACH_ROVERP7		ROVERP7			594
+pr818s			MACH_PR818S		PR818S			595
+trxpro			MACH_TRXPRO		TRXPRO			596
 nslu2			MACH_NSLU2		NSLU2			597
 e400			MACH_E400		E400			598
+trab			MACH_TRAB		TRAB			599
+cmc_pu2			MACH_CMC_PU2		CMC_PU2			600
+fulcrum			MACH_FULCRUM		FULCRUM			601
+netgate42x		MACH_NETGATE42X		NETGATE42X		602
+str710			MACH_STR710		STR710			603
 ixdpg425		MACH_IXDPG425		IXDPG425		604
+tomtomgo		MACH_TOMTOMGO		TOMTOMGO		605
 versatile_ab		MACH_VERSATILE_AB	VERSATILE_AB		606
 edb9307			MACH_EDB9307		EDB9307			607
+sg565			MACH_SG565		SG565			608
+lpd79524		MACH_LPD79524		LPD79524		609
+lpd79525		MACH_LPD79525		LPD79525		610
+rms100			MACH_RMS100		RMS100			611
 kb9200			MACH_KB9200		KB9200			612
 sx1			MACH_SX1		SX1			613
+hms39c7092		MACH_HMS39C7092		HMS39C7092		614
+armadillo		MACH_ARMADILLO		ARMADILLO		615
+ipcu			MACH_IPCU		IPCU			616
+loox720			MACH_LOOX720		LOOX720			617
 ixdp465			MACH_IXDP465		IXDP465			618
 ixdp2351		MACH_IXDP2351		IXDP2351		619
+adsvix			MACH_ADSVIX		ADSVIX			620
+dm270			MACH_DM270		DM270			621
+socltplus		MACH_SOCLTPLUS		SOCLTPLUS		622
+ecia			MACH_ECIA		ECIA			623
+cm4008			MACH_CM4008		CM4008			624
+p2001			MACH_P2001		P2001			625
+twister			MACH_TWISTER		TWISTER			626
+mudshark		MACH_MUDSHARK		MUDSHARK		627
+hb2			MACH_HB2		HB2			628
 iq80332			MACH_IQ80332		IQ80332			629
+sendt			MACH_SENDT		SENDT			630
+mx2jazz			MACH_MX2JAZZ		MX2JAZZ			631
+multiio			MACH_MULTIIO		MULTIIO			632
+hrdisplay		MACH_HRDISPLAY		HRDISPLAY		633
+mxc27530ads		MACH_MXC27530ADS	MXC27530ADS		634
+trizeps3		MACH_TRIZEPS3		TRIZEPS3		635
+zefeerdza		MACH_ZEFEERDZA		ZEFEERDZA		636
+zefeerdzb		MACH_ZEFEERDZB		ZEFEERDZB		637
+zefeerdzg		MACH_ZEFEERDZG		ZEFEERDZG		638
+zefeerdzn		MACH_ZEFEERDZN		ZEFEERDZN		639
+zefeerdzq		MACH_ZEFEERDZQ		ZEFEERDZQ		640
 gtwx5715		MACH_GTWX5715		GTWX5715		641
+astro_jack		MACH_ASTRO_JACK		ASTRO_JACK		643
+tip03			MACH_TIP03		TIP03			644
+a9200ec			MACH_A9200EC		A9200EC			645
+pnx0105			MACH_PNX0105		PNX0105			646
+adcpoecpu		MACH_ADCPOECPU		ADCPOECPU		647
 csb637			MACH_CSB637		CSB637			648
+mb9200			MACH_MB9200		MB9200			650
+kulun			MACH_KULUN		KULUN			651
+snapper			MACH_SNAPPER		SNAPPER			652
+optima			MACH_OPTIMA		OPTIMA			653
+dlhsbc			MACH_DLHSBC		DLHSBC			654
+x30			MACH_X30		X30			655
 n30			MACH_N30		N30			656
+manga_ks8695		MACH_MANGA_KS8695	MANGA_KS8695		657
+ajax			MACH_AJAX		AJAX			658
 nec_mp900		MACH_NEC_MP900		NEC_MP900		659
+vvtk1000		MACH_VVTK1000		VVTK1000		661
 kafa			MACH_KAFA		KAFA			662
+vvtk3000		MACH_VVTK3000		VVTK3000		663
+pimx1			MACH_PIMX1		PIMX1			664
+ollie			MACH_OLLIE		OLLIE			665
+skymax			MACH_SKYMAX		SKYMAX			666
+jazz			MACH_JAZZ		JAZZ			667
+tel_t3			MACH_TEL_T3		TEL_T3			668
+aisino_fcr255		MACH_AISINO_FCR255	AISINO_FCR255		669
+btweb			MACH_BTWEB		BTWEB			670
+dbg_lh79520		MACH_DBG_LH79520	DBG_LH79520		671
+cm41xx			MACH_CM41XX		CM41XX			672
 ts72xx			MACH_TS72XX		TS72XX			673
+nggpxa			MACH_NGGPXA		NGGPXA			674
+csb535			MACH_CSB535		CSB535			675
+csb536			MACH_CSB536		CSB536			676
+pxa_trakpod		MACH_PXA_TRAKPOD	PXA_TRAKPOD		677
+praxis			MACH_PRAXIS		PRAXIS			678
+lh75411			MACH_LH75411		LH75411			679
 otom			MACH_OTOM		OTOM			680
 nexcoder_2440		MACH_NEXCODER_2440	NEXCODER_2440		681
+loox410			MACH_LOOX410		LOOX410			682
+westlake		MACH_WESTLAKE		WESTLAKE		683
+nsb			MACH_NSB		NSB			684
+esl_sarva_stn		MACH_ESL_SARVA_STN	ESL_SARVA_STN		685
+esl_sarva_tft		MACH_ESL_SARVA_TFT	ESL_SARVA_TFT		686
+esl_sarva_iad		MACH_ESL_SARVA_IAD	ESL_SARVA_IAD		687
+esl_sarva_acc		MACH_ESL_SARVA_ACC	ESL_SARVA_ACC		688
+typhoon			MACH_TYPHOON		TYPHOON			689
+cnav			MACH_CNAV		CNAV			690
+a730			MACH_A730		A730			691
+netstar			MACH_NETSTAR		NETSTAR			692
+supercon		MACH_PHASEFALE_SUPERCON	PHASEFALE_SUPERCON	693
+shiva1100		MACH_SHIVA1100		SHIVA1100		694
+etexsc			MACH_ETEXSC		ETEXSC			695
+ixdpg465		MACH_IXDPG465		IXDPG465		696
+a9m2410			MACH_A9M2410		A9M2410			697
+a9m2440			MACH_A9M2440		A9M2440			698
+a9m9750			MACH_A9M9750		A9M9750			699
+a9m9360			MACH_A9M9360		A9M9360			700
+unc90			MACH_UNC90		UNC90			701
 eco920			MACH_ECO920		ECO920			702
+satview			MACH_SATVIEW		SATVIEW			703
 roadrunner		MACH_ROADRUNNER		ROADRUNNER		704
 at91rm9200ek		MACH_AT91RM9200EK	AT91RM9200EK		705
+gp32			MACH_GP32		GP32			706
+gem			MACH_GEM		GEM			707
+i858			MACH_I858		I858			708
+hx2750			MACH_HX2750		HX2750			709
+mxc91131evb		MACH_MXC91131EVB	MXC91131EVB		710
+p700			MACH_P700		P700			711
+cpe			MACH_CPE		CPE			712
 spitz			MACH_SPITZ		SPITZ			713
+nimbra340		MACH_NIMBRA340		NIMBRA340		714
+lpc22xx			MACH_LPC22XX		LPC22XX			715
+omap_comet3		MACH_COMET3		COMET3			716
+omap_comet4		MACH_COMET4		COMET4			717
+csb625			MACH_CSB625		CSB625			718
+fortunet2		MACH_FORTUNET2		FORTUNET2		719
+s5h2200			MACH_S5H2200		S5H2200			720
+optorm920		MACH_OPTORM920		OPTORM920		721
+adsbitsyxb		MACH_ADSBITSYXB		ADSBITSYXB		722
 adssphere		MACH_ADSSPHERE		ADSSPHERE		723
+adsportal		MACH_ADSPORTAL		ADSPORTAL		724
+ln2410sbc		MACH_LN2410SBC		LN2410SBC		725
+cb3rufc			MACH_CB3RUFC		CB3RUFC			726
+mp2usb			MACH_MP2USB		MP2USB			727
+ntnp425c		MACH_NTNP425C		NTNP425C		728
 colibri			MACH_COLIBRI		COLIBRI			729
+pcm7220			MACH_PCM7220		PCM7220			730
 gateway7001		MACH_GATEWAY7001	GATEWAY7001		731
 pcm027			MACH_PCM027		PCM027			732
+cmpxa			MACH_CMPXA		CMPXA			733
 anubis			MACH_ANUBIS		ANUBIS			734
+ite8152			MACH_ITE8152		ITE8152			735
+lpc3xxx			MACH_LPC3XXX		LPC3XXX			736
+puppeteer		MACH_PUPPETEER		PUPPETEER		737
+e570			MACH_E570		E570			739
+x50			MACH_X50		X50			740
+recon			MACH_RECON		RECON			741
+xboardgp8		MACH_XBOARDGP8		XBOARDGP8		742
+fpic2			MACH_FPIC2		FPIC2			743
 akita			MACH_AKITA		AKITA			744
+a81			MACH_A81		A81			745
+svm_sc25x		MACH_SVM_SC25X		SVM_SC25X		746
+vt020			MACH_VADATECH020	VADATECH020		747
+tli			MACH_TLI		TLI			748
+edb9315lc		MACH_EDB9315LC		EDB9315LC		749
+passec			MACH_PASSEC		PASSEC			750
+ds_tiger		MACH_DS_TIGER		DS_TIGER		751
+e310			MACH_E310		E310			752
 e330			MACH_E330		E330			753
+rt3000			MACH_RT3000		RT3000			754
 nokia770		MACH_NOKIA770		NOKIA770		755
+pnx0106			MACH_PNX0106		PNX0106			756
+hx21xx			MACH_HX21XX		HX21XX			757
+faraday			MACH_FARADAY		FARADAY			758
+sbc9312			MACH_SBC9312		SBC9312			759
+batman			MACH_BATMAN		BATMAN			760
+jpd201			MACH_JPD201		JPD201			761
+mipsa			MACH_MIPSA		MIPSA			762
+kacom			MACH_KACOM		KACOM			763
+swarcocpu		MACH_SWARCOCPU		SWARCOCPU		764
+swarcodsl		MACH_SWARCODSL		SWARCODSL		765
+blueangel		MACH_BLUEANGEL		BLUEANGEL		766
+hairygrama		MACH_HAIRYGRAMA		HAIRYGRAMA		767
+banff			MACH_BANFF		BANFF			768
 carmeva			MACH_CARMEVA		CARMEVA			769
+sam255			MACH_SAM255		SAM255			770
+ppm10			MACH_PPM10		PPM10			771
 edb9315a		MACH_EDB9315A		EDB9315A		772
+sunset			MACH_SUNSET		SUNSET			773
 stargate2		MACH_STARGATE2		STARGATE2		774
 intelmote2		MACH_INTELMOTE2		INTELMOTE2		775
 trizeps4		MACH_TRIZEPS4		TRIZEPS4		776
+mainstone2		MACH_MAINSTONE2		MAINSTONE2		777
+ez_ixp42x		MACH_EZ_IXP42X		EZ_IXP42X		778
+tapwave_zodiac		MACH_TAPWAVE_ZODIAC	TAPWAVE_ZODIAC		779
+universalmeter		MACH_UNIVERSALMETER	UNIVERSALMETER		780
+hicoarm9		MACH_HICOARM9		HICOARM9		781
 pnx4008			MACH_PNX4008		PNX4008			782
+kws6000			MACH_KWS6000		KWS6000			783
+portux920t		MACH_PORTUX920T		PORTUX920T		784
+ez_x5			MACH_EZ_X5		EZ_X5			785
+omap_rudolph		MACH_OMAP_RUDOLPH	OMAP_RUDOLPH		786
 cpuat91			MACH_CPUAT91		CPUAT91			787
+rea9200			MACH_REA9200		REA9200			788
+acts_pune_sa1110	MACH_ACTS_PUNE_SA1110	ACTS_PUNE_SA1110	789
+ixp425			MACH_IXP425		IXP425			790
+i30030ads		MACH_I30030ADS		I30030ADS		791
+perch			MACH_PERCH		PERCH			792
+eis05r1			MACH_EIS05R1		EIS05R1			793
+pepperpad		MACH_PEPPERPAD		PEPPERPAD		794
+sb3010			MACH_SB3010		SB3010			795
+rm9200			MACH_RM9200		RM9200			796
+dma03			MACH_DMA03		DMA03			797
+road_s101		MACH_ROAD_S101		ROAD_S101		798
 iq81340sc		MACH_IQ81340SC		IQ81340SC		799
+iq_nextgen_b		MACH_IQ_NEXTGEN_B	IQ_NEXTGEN_B		800
 iq81340mc		MACH_IQ81340MC		IQ81340MC		801
+iq_nextgen_d		MACH_IQ_NEXTGEN_D	IQ_NEXTGEN_D		802
+iq_nextgen_e		MACH_IQ_NEXTGEN_E	IQ_NEXTGEN_E		803
+mallow_at91		MACH_MALLOW_AT91	MALLOW_AT91		804
+cybertracker_i		MACH_CYBERTRACKER_I	CYBERTRACKER_I		805
+gesbc931x		MACH_GESBC931X		GESBC931X		806
+centipad		MACH_CENTIPAD		CENTIPAD		807
+armsoc			MACH_ARMSOC		ARMSOC			808
+se4200			MACH_SE4200		SE4200			809
+ems197a			MACH_EMS197A		EMS197A			810
 micro9			MACH_MICRO9		MICRO9			811
 micro9l			MACH_MICRO9L		MICRO9L			812
+uc5471dsp		MACH_UC5471DSP		UC5471DSP		813
+sj5471eng		MACH_SJ5471ENG		SJ5471ENG		814
+none			MACH_CMPXA26X		CMPXA26X		815
+nc1			MACH_NC			NC			816
 omap_palmte		MACH_OMAP_PALMTE	OMAP_PALMTE		817
+ajax52x			MACH_AJAX52X		AJAX52X			818
+siriustar		MACH_SIRIUSTAR		SIRIUSTAR		819
+iodata_hdlg		MACH_IODATA_HDLG	IODATA_HDLG		820
+at91rm9200utl		MACH_AT91RM9200UTL	AT91RM9200UTL		821
+biosafe			MACH_BIOSAFE		BIOSAFE			822
+mp1000			MACH_MP1000		MP1000			823
+parsy			MACH_PARSY		PARSY			824
+ccxp270			MACH_CCXP		CCXP			825
+omap_gsample		MACH_OMAP_GSAMPLE	OMAP_GSAMPLE		826
 realview_eb		MACH_REALVIEW_EB	REALVIEW_EB		827
+samoa			MACH_SAMOA		SAMOA			828
+palmt3			MACH_PALMT3		PALMT3			829
+i878			MACH_I878		I878			830
 borzoi			MACH_BORZOI		BORZOI			831
+gecko			MACH_GECKO		GECKO			832
+ds101			MACH_DS101		DS101			833
+omap_palmtt2		MACH_OMAP_PALMTT2	OMAP_PALMTT2		834
 palmld			MACH_PALMLD		PALMLD			835
+cc9c			MACH_CC9C		CC9C			836
+sbc1670			MACH_SBC1670		SBC1670			837
 ixdp28x5		MACH_IXDP28X5		IXDP28X5		838
 omap_palmtt		MACH_OMAP_PALMTT	OMAP_PALMTT		839
+ml696k			MACH_ML696K		ML696K			840
 arcom_zeus		MACH_ARCOM_ZEUS		ARCOM_ZEUS		841
 osiris			MACH_OSIRIS		OSIRIS			842
+maestro			MACH_MAESTRO		MAESTRO			843
 palmte2			MACH_PALMTE2		PALMTE2			844
+ixbbm			MACH_IXBBM		IXBBM			845
 mx27ads			MACH_MX27ADS		MX27ADS			846
+ax8004			MACH_AX8004		AX8004			847
 at91sam9261ek		MACH_AT91SAM9261EK	AT91SAM9261EK		848
 loft			MACH_LOFT		LOFT			849
+magpie			MACH_MAGPIE		MAGPIE			850
 mx21ads			MACH_MX21ADS		MX21ADS			851
+mb87m3400		MACH_MB87M3400		MB87M3400		852
+mguard_delta		MACH_MGUARD_DELTA	MGUARD_DELTA		853
+davinci_dvdp		MACH_DAVINCI_DVDP	DAVINCI_DVDP		854
+htcuniversal		MACH_HTCUNIVERSAL	HTCUNIVERSAL		855
+tpad			MACH_TPAD		TPAD			856
+roverp3			MACH_ROVERP3		ROVERP3			857
+jornada928		MACH_JORNADA928		JORNADA928		858
+mv88fxx81		MACH_MV88FXX81		MV88FXX81		859
+stmp36xx		MACH_STMP36XX		STMP36XX		860
+sxni79524		MACH_SXNI79524		SXNI79524		861
 ams_delta		MACH_AMS_DELTA		AMS_DELTA		862
+uranium			MACH_URANIUM		URANIUM			863
+ucon			MACH_UCON		UCON			864
 nas100d			MACH_NAS100D		NAS100D			865
+l083			MACH_L083_1000		L083_1000		866
+ezx			MACH_EZX		EZX			867
+pnx5220			MACH_PNX5220		PNX5220			868
+butte			MACH_BUTTE		BUTTE			869
+srm2			MACH_SRM2		SRM2			870
+dsbr			MACH_DSBR		DSBR			871
+crystalball		MACH_CRYSTALBALL	CRYSTALBALL		872
+tinypxa27x		MACH_TINYPXA27X		TINYPXA27X		873
+herbie			MACH_HERBIE		HERBIE			874
 magician		MACH_MAGICIAN		MAGICIAN		875
+cm4002			MACH_CM4002		CM4002			876
+b4			MACH_B4			B4			877
+maui			MACH_MAUI		MAUI			878
+cybertracker_g		MACH_CYBERTRACKER_G	CYBERTRACKER_G		879
 nxdkn			MACH_NXDKN		NXDKN			880
+mio8390			MACH_MIO8390		MIO8390			881
+omi_board		MACH_OMI_BOARD		OMI_BOARD		882
+mx21civ			MACH_MX21CIV		MX21CIV			883
+mahi_cdac		MACH_MAHI_CDAC		MAHI_CDAC		884
 palmtx			MACH_PALMTX		PALMTX			885
 s3c2413			MACH_S3C2413		S3C2413			887
+samsys_ep0		MACH_SAMSYS_EP0		SAMSYS_EP0		888
+wg302v1			MACH_WG302V1		WG302V1			889
 wg302v2			MACH_WG302V2		WG302V2			890
+eb42x			MACH_EB42X		EB42X			891
+iq331es			MACH_IQ331ES		IQ331ES			892
+cosydsp			MACH_COSYDSP		COSYDSP			893
+uplat7d_proto		MACH_UPLAT7D		UPLAT7D			894
+ptdavinci		MACH_PTDAVINCI		PTDAVINCI		895
+mbus			MACH_MBUS		MBUS			896
+nadia2vb		MACH_NADIA2VB		NADIA2VB		897
+r1000			MACH_R1000		R1000			898
+hw90250			MACH_HW90250		HW90250			899
 omap_2430sdp		MACH_OMAP_2430SDP	OMAP_2430SDP		900
 davinci_evm		MACH_DAVINCI_EVM	DAVINCI_EVM		901
+omap_tornado		MACH_OMAP_TORNADO	OMAP_TORNADO		902
+olocreek		MACH_OLOCREEK		OLOCREEK		903
 palmz72			MACH_PALMZ72		PALMZ72			904
 nxdb500			MACH_NXDB500		NXDB500			905
 apf9328			MACH_APF9328		APF9328			906
+omap_wipoq		MACH_OMAP_WIPOQ		OMAP_WIPOQ		907
+omap_twip		MACH_OMAP_TWIP		OMAP_TWIP		908
+treo650			MACH_TREO650		TREO650			909
+acumen			MACH_ACUMEN		ACUMEN			910
+xp100			MACH_XP100		XP100			911
+fs2410			MACH_FS2410		FS2410			912
+pxa270_cerf		MACH_PXA270_CERF	PXA270_CERF		913
+sq2ftlpalm		MACH_SQ2FTLPALM		SQ2FTLPALM		914
+bsemserver		MACH_BSEMSERVER		BSEMSERVER		915
+netclient		MACH_NETCLIENT		NETCLIENT		916
 palmt5			MACH_PALMT5		PALMT5			917
 palmtc			MACH_PALMTC		PALMTC			918
 omap_apollon		MACH_OMAP_APOLLON	OMAP_APOLLON		919
+mxc30030evb		MACH_MXC30030EVB	MXC30030EVB		920
+rea_cpu2		MACH_REA_2D		REA_2D			921
+eti3e524		MACH_TI3E524		TI3E524			922
 ateb9200		MACH_ATEB9200		ATEB9200		923
+auckland		MACH_AUCKLAND		AUCKLAND		924
+ak3220m			MACH_AK3320M		AK3320M			925
+duramax			MACH_DURAMAX		DURAMAX			926
 n35			MACH_N35		N35			927
+pronghorn		MACH_PRONGHORN		PRONGHORN		928
+fundy			MACH_FUNDY		FUNDY			929
 logicpd_pxa270		MACH_LOGICPD_PXA270	LOGICPD_PXA270		930
+cpu777			MACH_CPU777		CPU777			931
+simicon9201		MACH_SIMICON9201	SIMICON9201		932
+leap2_hpm		MACH_LEAP2_HPM		LEAP2_HPM		933
+cm922txa10		MACH_CM922TXA10		CM922TXA10		934
+sandgate		MACH_PXA		PXA			935
+sandgate2		MACH_SANDGATE2		SANDGATE2		936
+sandgate2g		MACH_SANDGATE2G		SANDGATE2G		937
+sandgate2p		MACH_SANDGATE2P		SANDGATE2P		938
+fred_jack		MACH_FRED_JACK		FRED_JACK		939
+ttg_color1		MACH_TTG_COLOR1		TTG_COLOR1		940
 nxeb500hmi		MACH_NXEB500HMI		NXEB500HMI		941
+netdcu8			MACH_NETDCU8		NETDCU8			942
+ng_fvx538		MACH_NG_FVX538		NG_FVX538		944
+ng_fvs338		MACH_NG_FVS338		NG_FVS338		945
+pnx4103			MACH_PNX4103		PNX4103			946
+hesdb			MACH_HESDB		HESDB			947
+xsilo			MACH_XSILO		XSILO			948
 espresso		MACH_ESPRESSO		ESPRESSO		949
+emlc			MACH_EMLC		EMLC			950
+sisteron		MACH_SISTERON		SISTERON		951
 rx1950			MACH_RX1950		RX1950			952
+tsc_venus		MACH_TSC_VENUS		TSC_VENUS		953
+ds101j			MACH_DS101J		DS101J			954
+mxc30030ads		MACH_MXC30030ADS	MXC30030ADS		955
+fujitsu_wimaxsoc	MACH_FUJITSU_WIMAXSOC	FUJITSU_WIMAXSOC	956
+dualpcmodem		MACH_DUALPCMODEM	DUALPCMODEM		957
 gesbc9312		MACH_GESBC9312		GESBC9312		958
+htcapache		MACH_HTCAPACHE		HTCAPACHE		959
+ixdp435			MACH_IXDP435		IXDP435			960
+catprovt100		MACH_CATPROVT100	CATPROVT100		961
+picotux1xx		MACH_PICOTUX1XX		PICOTUX1XX		962
 picotux2xx		MACH_PICOTUX2XX		PICOTUX2XX		963
 dsmg600			MACH_DSMG600		DSMG600			964
+empc2			MACH_EMPC2		EMPC2			965
+ventura			MACH_VENTURA		VENTURA			966
+phidget_sbc		MACH_PHIDGET_SBC	PHIDGET_SBC		967
+ij3k			MACH_IJ3K		IJ3K			968
+pisgah			MACH_PISGAH		PISGAH			969
 omap_fsample		MACH_OMAP_FSAMPLE	OMAP_FSAMPLE		970
+sg720			MACH_SG720		SG720			971
+redfox			MACH_REDFOX		REDFOX			972
+mysh_ep9315_1		MACH_MYSH_EP9315_1	MYSH_EP9315_1		973
+tpf106			MACH_TPF106		TPF106			974
+at91rm9200kg		MACH_AT91RM9200KG	AT91RM9200KG		975
+rcmt2			MACH_SLEDB		SLEDB			976
+ontrack			MACH_ONTRACK		ONTRACK			977
+pm1200			MACH_PM1200		PM1200			978
+ess24562		MACH_ESS24XXX		ESS24XXX		979
+coremp7			MACH_COREMP7		COREMP7			980
+nexcoder_6446		MACH_NEXCODER_6446	NEXCODER_6446		981
+stvc8380		MACH_STVC8380		STVC8380		982
+teklynx			MACH_TEKLYNX		TEKLYNX			983
+carbonado		MACH_CARBONADO		CARBONADO		984
+sysmos_mp730		MACH_SYSMOS_MP730	SYSMOS_MP730		985
 snapper_cl15		MACH_SNAPPER_CL15	SNAPPER_CL15		986
+pgigim			MACH_PGIGIM		PGIGIM			987
+ptx9160p2		MACH_PTX9160P2		PTX9160P2		988
+dcore1			MACH_DCORE1		DCORE1			989
+victorpxa		MACH_VICTORPXA		VICTORPXA		990
+mx2dtb			MACH_MX2DTB		MX2DTB			991
+pxa_irex_er0100		MACH_PXA_IREX_ER0100	PXA_IREX_ER0100		992
 omap_palmz71		MACH_OMAP_PALMZ71	OMAP_PALMZ71		993
+bartec_deg		MACH_BARTEC_DEG		BARTEC_DEG		994
+hw50251			MACH_HW50251		HW50251			995
+ibox			MACH_IBOX		IBOX			996
+atlaslh7a404		MACH_ATLASLH7A404	ATLASLH7A404		997
+pt2026			MACH_PT2026		PT2026			998
+htcalpine		MACH_HTCALPINE		HTCALPINE		999
+bartec_vtu		MACH_BARTEC_VTU		BARTEC_VTU		1000
+vcoreii			MACH_VCOREII		VCOREII			1001
+pdnb3			MACH_PDNB3		PDNB3			1002
+htcbeetles		MACH_HTCBEETLES		HTCBEETLES		1003
+s3c6400			MACH_S3C6400		S3C6400			1004
+s3c2443			MACH_S3C2443		S3C2443			1005
+omap_ldk		MACH_OMAP_LDK		OMAP_LDK		1006
+smdk2460		MACH_SMDK2460		SMDK2460		1007
+smdk2440		MACH_SMDK2440		SMDK2440		1008
 smdk2412		MACH_SMDK2412		SMDK2412		1009
+webbox			MACH_WEBBOX		WEBBOX			1010
+cwwndp			MACH_CWWNDP		CWWNDP			1011
+i839			MACH_DRAGON		DRAGON			1012
+opendo_cpu_board	MACH_OPENDO_CPU_BOARD	OPENDO_CPU_BOARD	1013
+ccm2200			MACH_CCM2200		CCM2200			1014
+etwarm			MACH_ETWARM		ETWARM			1015
+m93030			MACH_M93030		M93030			1016
+cc7u			MACH_CC7U		CC7U			1017
+mtt_ranger		MACH_MTT_RANGER		MTT_RANGER		1018
+nexus			MACH_NEXUS		NEXUS			1019
+desman			MACH_DESMAN		DESMAN			1020
+bkde303			MACH_BKDE303		BKDE303			1021
 smdk2413		MACH_SMDK2413		SMDK2413		1022
+aml_m7200		MACH_AML_M7200		AML_M7200		1023
 aml_m5900		MACH_AML_M5900		AML_M5900		1024
+sg640			MACH_SG640		SG640			1025
+edg79524		MACH_EDG79524		EDG79524		1026
+ai2410			MACH_AI2410		AI2410			1027
+ixp465			MACH_IXP465		IXP465			1028
 balloon3		MACH_BALLOON3		BALLOON3		1029
+heins			MACH_HEINS		HEINS			1030
+mpluseva		MACH_MPLUSEVA		MPLUSEVA		1031
+rt042			MACH_RT042		RT042			1032
+cwiem			MACH_CWIEM		CWIEM			1033
+cm_x270			MACH_CM_X270		CM_X270			1034
+cm_x255			MACH_CM_X255		CM_X255			1035
+esh_at91		MACH_ESH_AT91		ESH_AT91		1036
+sandgate3		MACH_SANDGATE3		SANDGATE3		1037
+primo			MACH_PRIMO		PRIMO			1038
+gemstone		MACH_GEMSTONE		GEMSTONE		1039
+pronghorn_metro		MACH_PRONGHORNMETRO	PRONGHORNMETRO		1040
+sidewinder		MACH_SIDEWINDER		SIDEWINDER		1041
+picomod1		MACH_PICOMOD1		PICOMOD1		1042
+sg590			MACH_SG590		SG590			1043
+akai9307		MACH_AKAI9307		AKAI9307		1044
+fontaine		MACH_FONTAINE		FONTAINE		1045
+wombat			MACH_WOMBAT		WOMBAT			1046
+acq300			MACH_ACQ300		ACQ300			1047
+mod272			MACH_MOD_270		MOD_270			1048
+vmc_vc0820		MACH_VC0820		VC0820			1049
+ani_aim			MACH_ANI_AIM		ANI_AIM			1050
+jellyfish		MACH_JELLYFISH		JELLYFISH		1051
+amanita			MACH_AMANITA		AMANITA			1052
+vlink			MACH_VLINK		VLINK			1053
+dexflex			MACH_DEXFLEX		DEXFLEX			1054
+eigen_ttq		MACH_EIGEN_TTQ		EIGEN_TTQ		1055
+arcom_titan		MACH_ARCOM_TITAN	ARCOM_TITAN		1056
+tabla			MACH_TABLA		TABLA			1057
+mdirac3			MACH_MDIRAC3		MDIRAC3			1058
+mrhfbp2			MACH_MRHFBP2		MRHFBP2			1059
+at91rm9200rb		MACH_AT91RM9200RB	AT91RM9200RB		1060
+ani_apm			MACH_ANI_APM		ANI_APM			1061
+ella1			MACH_ELLA1		ELLA1			1062
+inhand_pxa27x		MACH_INHAND_PXA27X	INHAND_PXA27X		1063
+inhand_pxa25x		MACH_INHAND_PXA25X	INHAND_PXA25X		1064
+empos_xm		MACH_EMPOS_XM		EMPOS_XM		1065
+empos			MACH_EMPOS		EMPOS			1066
+empos_tiny		MACH_EMPOS_TINY		EMPOS_TINY		1067
+empos_sm		MACH_EMPOS_SM		EMPOS_SM		1068
+egret			MACH_EGRET		EGRET			1069
+ostrich			MACH_OSTRICH		OSTRICH			1070
+n50			MACH_N50		N50			1071
 ecbat91			MACH_ECBAT91		ECBAT91			1072
+stareast		MACH_STAREAST		STAREAST		1073
+dspg_dw			MACH_DSPG_DW		DSPG_DW			1074
 onearm			MACH_ONEARM		ONEARM			1075
+mrg110_6		MACH_MRG110_6		MRG110_6		1076
+wrt300nv2		MACH_WRT300NV2		WRT300NV2		1077
+xm_bulverde		MACH_XM_BULVERDE	XM_BULVERDE		1078
+msm6100			MACH_MSM6100		MSM6100			1079
+eti_b1			MACH_ETI_B1		ETI_B1			1080
+za9l_series		MACH_ZILOG_ZA9L		ZILOG_ZA9L		1081
+bit2440			MACH_BIT2440		BIT2440			1082
+nbi			MACH_NBI		NBI			1083
 smdk2443		MACH_SMDK2443		SMDK2443		1084
+vdavinci		MACH_VDAVINCI		VDAVINCI		1085
+atc6			MACH_ATC6		ATC6			1086
+multmdw			MACH_MULTMDW		MULTMDW			1087
+mba2440			MACH_MBA2440		MBA2440			1088
+ecsd			MACH_ECSD		ECSD			1089
+palmz31			MACH_PALMZ31		PALMZ31			1090
 fsg			MACH_FSG		FSG			1091
+razor101		MACH_RAZOR101		RAZOR101		1092
+opera_tdm		MACH_OPERA_TDM		OPERA_TDM		1093
+comcerto		MACH_COMCERTO		COMCERTO		1094
+tb0319			MACH_TB0319		TB0319			1095
+kws8000			MACH_KWS8000		KWS8000			1096
+b2			MACH_B2			B2			1097
+lcl54			MACH_LCL54		LCL54			1098
 at91sam9260ek		MACH_AT91SAM9260EK	AT91SAM9260EK		1099
 glantank		MACH_GLANTANK		GLANTANK		1100
 n2100			MACH_N2100		N2100			1101
+n4100			MACH_N4100		N4100			1102
+rsc4			MACH_VERTICAL_RSC4	VERTICAL_RSC4		1103
+sg8100			MACH_SG8100		SG8100			1104
+im42xx			MACH_IM42XX		IM42XX			1105
+ftxx			MACH_FTXX		FTXX			1106
+lwfusion		MACH_LWFUSION		LWFUSION		1107
 qt2410			MACH_QT2410		QT2410			1108
 kixrp435		MACH_KIXRP435		KIXRP435		1109
+ccw9c			MACH_CCW9C		CCW9C			1110
+dabhs			MACH_DABHS		DABHS			1111
+gzmx			MACH_GZMX		GZMX			1112
+ipnw100ap		MACH_IPNW100AP		IPNW100AP		1113
 cc9p9360dev		MACH_CC9P9360DEV	CC9P9360DEV		1114
+cc9p9750dev		MACH_CC9P9750DEV	CC9P9750DEV		1115
+cc9p9360val		MACH_CC9P9360VAL	CC9P9360VAL		1116
+cc9p9750val		MACH_CC9P9750VAL	CC9P9750VAL		1117
+nx70v			MACH_NX70V		NX70V			1118
+at91rm9200df		MACH_AT91RM9200DF	AT91RM9200DF		1119
+se_pilot2		MACH_SE_PILOT2		SE_PILOT2		1120
+mtcn_t800		MACH_MTCN_T800		MTCN_T800		1121
+vcmx212			MACH_VCMX212		VCMX212			1122
+lynx			MACH_LYNX		LYNX			1123
+at91sam9260id		MACH_AT91SAM9260ID	AT91SAM9260ID		1124
+hw86052			MACH_HW86052		HW86052			1125
+pilz_pmi3		MACH_PILZ_PMI3		PILZ_PMI3		1126
 edb9302a		MACH_EDB9302A		EDB9302A		1127
 edb9307a		MACH_EDB9307A		EDB9307A		1128
+ct_dfs			MACH_CT_DFS		CT_DFS			1129
+pilz_pmi4		MACH_PILZ_PMI4		PILZ_PMI4		1130
+xceednp_ixp		MACH_XCEEDNP_IXP	XCEEDNP_IXP		1131
+smdk2442b		MACH_SMDK2442B		SMDK2442B		1132
+xnode			MACH_XNODE		XNODE			1133
+aidx270			MACH_AIDX270		AIDX270			1134
+rema			MACH_REMA		REMA			1135
+bps1000			MACH_BPS1000		BPS1000			1136
+hw90350			MACH_HW90350		HW90350			1137
 omap_3430sdp		MACH_OMAP_3430SDP	OMAP_3430SDP		1138
+bluetouch		MACH_BLUETOUCH		BLUETOUCH		1139
 vstms			MACH_VSTMS		VSTMS			1140
+xsbase270		MACH_XSBASE270		XSBASE270		1141
+at91sam9260ek_cn	MACH_AT91SAM9260EK_CN	AT91SAM9260EK_CN	1142
+adsturboxb		MACH_ADSTURBOXB		ADSTURBOXB		1143
+oti4110			MACH_OTI4110		OTI4110			1144
+hme_pxa			MACH_HME_PXA		HME_PXA			1145
+deisterdca		MACH_DEISTERDCA		DEISTERDCA		1146
+ces_ssem2		MACH_CES_SSEM2		CES_SSEM2		1147
+ces_mtr			MACH_CES_MTR		CES_MTR			1148
+tds_avng_sbc		MACH_TDS_AVNG_SBC	TDS_AVNG_SBC		1149
+everest			MACH_EVEREST		EVEREST			1150
+pnx4010			MACH_PNX4010		PNX4010			1151
+oxnas			MACH_OXNAS		OXNAS			1152
+fiori			MACH_FIORI		FIORI			1153
+ml1200			MACH_ML1200		ML1200			1154
+pecos			MACH_PECOS		PECOS			1155
+nb2xxx			MACH_NB2XXX		NB2XXX			1156
+hw6900			MACH_HW6900		HW6900			1157
+cdcs_quoll		MACH_CDCS_QUOLL		CDCS_QUOLL		1158
+quicksilver		MACH_QUICKSILVER	QUICKSILVER		1159
+uplat926		MACH_UPLAT926		UPLAT926		1160
+dep2410_dep2410		MACH_DEP2410_THOMAS	DEP2410_THOMAS		1161
+dtk2410			MACH_DTK2410		DTK2410			1162
+chili			MACH_CHILI		CHILI			1163
+demeter			MACH_DEMETER		DEMETER			1164
+dionysus		MACH_DIONYSUS		DIONYSUS		1165
+as352x			MACH_AS352X		AS352X			1166
+service			MACH_SERVICE		SERVICE			1167
+cs_e9301		MACH_CS_E9301		CS_E9301		1168
 micro9m			MACH_MICRO9M		MICRO9M			1169
+ia_mospck		MACH_IA_MOSPCK		IA_MOSPCK		1170
+ql201b			MACH_QL201B		QL201B			1171
+bbm			MACH_BBM		BBM			1174
+exxx			MACH_EXXX		EXXX			1175
+wma11b			MACH_WMA11B		WMA11B			1176
+pelco_atlas		MACH_PELCO_ATLAS	PELCO_ATLAS		1177
+g500			MACH_G500		G500			1178
 bug			MACH_BUG		BUG			1179
+mx33ads			MACH_MX33ADS		MX33ADS			1180
+chub			MACH_CHUB		CHUB			1181
+neo1973_gta01		MACH_NEO1973_GTA01	NEO1973_GTA01		1182
+w90n740			MACH_W90N740		W90N740			1183
+medallion_sa2410	MACH_MEDALLION_SA2410	MEDALLION_SA2410	1184
+ia_cpu_9200_2		MACH_IA_CPU_9200_2	IA_CPU_9200_2		1185
+dimmrm9200		MACH_DIMMRM9200		DIMMRM9200		1186
+pm9261			MACH_PM9261		PM9261			1187
+ml7304			MACH_ML7304		ML7304			1189
+ucp250			MACH_UCP250		UCP250			1190
+intboard		MACH_INTBOARD		INTBOARD		1191
+gulfstream		MACH_GULFSTREAM		GULFSTREAM		1192
+labquest		MACH_LABQUEST		LABQUEST		1193
+vcmx313			MACH_VCMX313		VCMX313			1194
+urg200			MACH_URG200		URG200			1195
+cpux255lcdnet		MACH_CPUX255LCDNET	CPUX255LCDNET		1196
+netdcu9			MACH_NETDCU9		NETDCU9			1197
+netdcu10		MACH_NETDCU10		NETDCU10		1198
+dspg_dga		MACH_DSPG_DGA		DSPG_DGA		1199
+dspg_dvw		MACH_DSPG_DVW		DSPG_DVW		1200
+solos			MACH_SOLOS		SOLOS			1201
 at91sam9263ek		MACH_AT91SAM9263EK	AT91SAM9263EK		1202
+osstbox			MACH_OSSTBOX		OSSTBOX			1203
+kbat9261		MACH_KBAT9261		KBAT9261		1204
+ct1100			MACH_CT1100		CT1100			1205
+akcppxa			MACH_AKCPPXA		AKCPPXA			1206
+ochaya1020		MACH_OCHAYA1020		OCHAYA1020		1207
+hitrack			MACH_HITRACK		HITRACK			1208
+syme1			MACH_SYME1		SYME1			1209
+syhl1			MACH_SYHL1		SYHL1			1210
+empca400		MACH_EMPCA400		EMPCA400		1211
 em7210			MACH_EM7210		EM7210			1212
+htchermes		MACH_HTCHERMES		HTCHERMES		1213
+eti_c1			MACH_ETI_C1		ETI_C1			1214
+ac100			MACH_AC100		AC100			1216
+sneetch			MACH_SNEETCH		SNEETCH			1217
+studentmate		MACH_STUDENTMATE	STUDENTMATE		1218
+zir2410			MACH_ZIR2410		ZIR2410			1219
+zir2413			MACH_ZIR2413		ZIR2413			1220
+dlonip3			MACH_DLONIP3		DLONIP3			1221
+instream		MACH_INSTREAM		INSTREAM		1222
+ambarella		MACH_AMBARELLA		AMBARELLA		1223
+nevis			MACH_NEVIS		NEVIS			1224
+htc_trinity		MACH_HTC_TRINITY	HTC_TRINITY		1225
+ql202b			MACH_QL202B		QL202B			1226
 vpac270			MACH_VPAC270		VPAC270			1227
+rd129			MACH_RD129		RD129			1228
+htcwizard		MACH_HTCWIZARD		HTCWIZARD		1229
 treo680			MACH_TREO680		TREO680			1230
+tecon_tmezon		MACH_TECON_TMEZON	TECON_TMEZON		1231
 zylonite		MACH_ZYLONITE		ZYLONITE		1233
+gene1270		MACH_GENE1270		GENE1270		1234
+zir2412			MACH_ZIR2412		ZIR2412			1235
 mx31lite		MACH_MX31LITE		MX31LITE		1236
+t700wx			MACH_T700WX		T700WX			1237
+vf100			MACH_VF100		VF100			1238
+nsb2			MACH_NSB2		NSB2			1239
+nxhmi_bb		MACH_NXHMI_BB		NXHMI_BB		1240
+nxhmi_re		MACH_NXHMI_RE		NXHMI_RE		1241
+n4100pro		MACH_N4100PRO		N4100PRO		1242
+sam9260			MACH_SAM9260		SAM9260			1243
+omap_treo600		MACH_OMAP_TREO600	OMAP_TREO600		1244
+indy2410		MACH_INDY2410		INDY2410		1245
+nelt_a			MACH_NELT_A		NELT_A			1246
+n311			MACH_N311		N311			1248
+at91sam9260vgk		MACH_AT91SAM9260VGK	AT91SAM9260VGK		1249
+at91leppe		MACH_AT91LEPPE		AT91LEPPE		1250
+at91lepccn		MACH_AT91LEPCCN		AT91LEPCCN		1251
+apc7100			MACH_APC7100		APC7100			1252
+stargazer		MACH_STARGAZER		STARGAZER		1253
+sonata			MACH_SONATA		SONATA			1254
+schmoogie		MACH_SCHMOOGIE		SCHMOOGIE		1255
+aztool			MACH_AZTOOL		AZTOOL			1256
 mioa701			MACH_MIOA701		MIOA701			1257
+sxni9260		MACH_SXNI9260		SXNI9260		1258
+mxc27520evb		MACH_MXC27520EVB	MXC27520EVB		1259
 armadillo5x0		MACH_ARMADILLO5X0	ARMADILLO5X0		1260
+mb9260			MACH_MB9260		MB9260			1261
+mb9263			MACH_MB9263		MB9263			1262
+ipac9302		MACH_IPAC9302		IPAC9302		1263
 cc9p9360js		MACH_CC9P9360JS		CC9P9360JS		1264
+gallium			MACH_GALLIUM		GALLIUM			1265
+msc2410			MACH_MSC2410		MSC2410			1266
+ghi270			MACH_GHI270		GHI270			1267
+davinci_leonardo	MACH_DAVINCI_LEONARDO	DAVINCI_LEONARDO	1268
+oiab			MACH_OIAB		OIAB			1269
 smdk6400		MACH_SMDK6400		SMDK6400		1270
 nokia_n800		MACH_NOKIA_N800		NOKIA_N800		1271
+greenphone		MACH_GREENPHONE		GREENPHONE		1272
+compex42x		MACH_COMPEXWP18		COMPEXWP18		1273
+xmate			MACH_XMATE		XMATE			1274
+energizer		MACH_ENERGIZER		ENERGIZER		1275
+ime1			MACH_IME1		IME1			1276
+sweda_tms		MACH_SWEDATMS		SWEDATMS		1277
+ntnp435c		MACH_NTNP435C		NTNP435C		1278
+spectro2		MACH_SPECTRO2		SPECTRO2		1279
+h6039			MACH_H6039		H6039			1280
 ep80219			MACH_EP80219		EP80219			1281
+samoa_ii		MACH_SAMOA_II		SAMOA_II		1282
+cwmxl			MACH_CWMXL		CWMXL			1283
+as9200			MACH_AS9200		AS9200			1284
+sfx1149			MACH_SFX1149		SFX1149			1285
+navi010			MACH_NAVI010		NAVI010			1286
+multmdp			MACH_MULTMDP		MULTMDP			1287
+scb9520			MACH_SCB9520		SCB9520			1288
+htcathena		MACH_HTCATHENA		HTCATHENA		1289
+xp179			MACH_XP179		XP179			1290
+h4300			MACH_H4300		H4300			1291
 goramo_mlr		MACH_GORAMO_MLR		GORAMO_MLR		1292
+mxc30020evb		MACH_MXC30020EVB	MXC30020EVB		1293
+adsbitsyg5		MACH_ADSBITSYG5		ADSBITSYG5		1294
+adsportalplus		MACH_ADSPORTALPLUS	ADSPORTALPLUS		1295
+mmsp2plus		MACH_MMSP2PLUS		MMSP2PLUS		1296
 em_x270			MACH_EM_X270		EM_X270			1297
+tpp302			MACH_TPP302		TPP302			1298
+tpp104			MACH_TPM104		TPM104			1299
+tpm102			MACH_TPM102		TPM102			1300
+tpm109			MACH_TPM109		TPM109			1301
+fbxo1			MACH_FBXO1		FBXO1			1302
+hxd8			MACH_HXD8		HXD8			1303
 neo1973_gta02		MACH_NEO1973_GTA02	NEO1973_GTA02		1304
+emtest			MACH_EMTEST		EMTEST			1305
+ad6900			MACH_AD6900		AD6900			1306
+europa			MACH_EUROPA		EUROPA			1307
+metroconnect		MACH_METROCONNECT	METROCONNECT		1308
+ez_s2410		MACH_EZ_S2410		EZ_S2410		1309
+ez_s2440		MACH_EZ_S2440		EZ_S2440		1310
+ez_ep9312		MACH_EZ_EP9312		EZ_EP9312		1311
+ez_ep9315		MACH_EZ_EP9315		EZ_EP9315		1312
+ez_x7			MACH_EZ_X7		EZ_X7			1313
+godotdb			MACH_GODOTDB		GODOTDB			1314
+mistral			MACH_MISTRAL		MISTRAL			1315
+msm			MACH_MSM		MSM			1316
+ct5910			MACH_CT5910		CT5910			1317
+ct5912			MACH_CT5912		CT5912			1318
+argonst_mp		MACH_HYNET_INE		HYNET_INE		1319
+hynet_app		MACH_HYNET_APP		HYNET_APP		1320
+msm7200			MACH_MSM7200		MSM7200			1321
+msm7600			MACH_MSM7600		MSM7600			1322
+ceb255			MACH_CEB255		CEB255			1323
+ciel			MACH_CIEL		CIEL			1324
+slm5650			MACH_SLM5650		SLM5650			1325
 at91sam9rlek		MACH_AT91SAM9RLEK	AT91SAM9RLEK		1326
+comtech_router		MACH_COMTECH_ROUTER	COMTECH_ROUTER		1327
+sbc2410x		MACH_SBC2410X		SBC2410X		1328
+at4x0bd			MACH_AT4X0BD		AT4X0BD			1329
+cbifr			MACH_CBIFR		CBIFR			1330
+arcom_quantum		MACH_ARCOM_QUANTUM	ARCOM_QUANTUM		1331
+matrix520		MACH_MATRIX520		MATRIX520		1332
+matrix510		MACH_MATRIX510		MATRIX510		1333
+matrix500		MACH_MATRIX500		MATRIX500		1334
+m501			MACH_M501		M501			1335
+aaeon1270		MACH_AAEON1270		AAEON1270		1336
+matrix500ev		MACH_MATRIX500EV	MATRIX500EV		1337
+pac500			MACH_PAC500		PAC500			1338
+pnx8181			MACH_PNX8181		PNX8181			1339
 colibri320		MACH_COLIBRI320		COLIBRI320		1340
+aztoolbb		MACH_AZTOOLBB		AZTOOLBB		1341
+aztoolg2		MACH_AZTOOLG2		AZTOOLG2		1342
+dvlhost			MACH_DVLHOST		DVLHOST			1343
+zir9200			MACH_ZIR9200		ZIR9200			1344
+zir9260			MACH_ZIR9260		ZIR9260			1345
+cocopah			MACH_COCOPAH		COCOPAH			1346
+nds			MACH_NDS		NDS			1347
+rosencrantz		MACH_ROSENCRANTZ	ROSENCRANTZ		1348
+fttx_odsc		MACH_FTTX_ODSC		FTTX_ODSC		1349
+classe_r6904		MACH_CLASSE_R6904	CLASSE_R6904		1350
 cam60			MACH_CAM60		CAM60			1351
+mxc30031ads		MACH_MXC30031ADS	MXC30031ADS		1352
+datacall		MACH_DATACALL		DATACALL		1353
 at91eb01		MACH_AT91EB01		AT91EB01		1354
+rty			MACH_RTY		RTY			1355
+dwl2100			MACH_DWL2100		DWL2100			1356
+vinsi			MACH_VINSI		VINSI			1357
 db88f5281		MACH_DB88F5281		DB88F5281		1358
 csb726			MACH_CSB726		CSB726			1359
+tik27			MACH_TIK27		TIK27			1360
+mx_uc7420		MACH_MX_UC7420		MX_UC7420		1361
+rirm3			MACH_RIRM3		RIRM3			1362
+pelco_odyssey		MACH_PELCO_ODYSSEY	PELCO_ODYSSEY		1363
+adx_abox		MACH_ADX_ABOX		ADX_ABOX		1365
+adx_tpid		MACH_ADX_TPID		ADX_TPID		1366
+minicheck		MACH_MINICHECK		MINICHECK		1367
+idam			MACH_IDAM		IDAM			1368
+mario_mx		MACH_MARIO_MX		MARIO_MX		1369
+vi1888			MACH_VI1888		VI1888			1370
+zr4230			MACH_ZR4230		ZR4230			1371
+t1_ix_blue		MACH_T1_IX_BLUE		T1_IX_BLUE		1372
+syhq2			MACH_SYHQ2		SYHQ2			1373
+computime_r3		MACH_COMPUTIME_R3	COMPUTIME_R3		1374
+oratis			MACH_ORATIS		ORATIS			1375
+mikko			MACH_MIKKO		MIKKO			1376
+holon			MACH_HOLON		HOLON			1377
+olip8			MACH_OLIP8		OLIP8			1378
+ghi270hg		MACH_GHI270HG		GHI270HG		1379
 davinci_dm6467_evm	MACH_DAVINCI_DM6467_EVM	DAVINCI_DM6467_EVM	1380
 davinci_dm355_evm	MACH_DAVINCI_DM355_EVM	DAVINCI_DM355_EVM	1381
+blackriver		MACH_BLACKRIVER		BLACKRIVER		1383
+sandgate_wp		MACH_SANDGATEWP		SANDGATEWP		1384
+cdotbwsg		MACH_CDOTBWSG		CDOTBWSG		1385
+quark963		MACH_QUARK963		QUARK963		1386
+csb735			MACH_CSB735		CSB735			1387
 littleton		MACH_LITTLETON		LITTLETON		1388
+mio_p550		MACH_MIO_P550		MIO_P550		1389
+motion2440		MACH_MOTION2440		MOTION2440		1390
+imm500			MACH_IMM500		IMM500			1391
+homematic		MACH_HOMEMATIC		HOMEMATIC		1392
+ermine			MACH_ERMINE		ERMINE			1393
+kb9202b			MACH_KB9202B		KB9202B			1394
+hs1xx			MACH_HS1XX		HS1XX			1395
+studentmate2440		MACH_STUDENTMATE2440	STUDENTMATE2440		1396
+arvoo_l1_z1		MACH_ARVOO_L1_Z1	ARVOO_L1_Z1		1397
+dep2410k		MACH_DEP2410K		DEP2410K		1398
+xxsvideo		MACH_XXSVIDEO		XXSVIDEO		1399
+im4004			MACH_IM4004		IM4004			1400
+ochaya1050		MACH_OCHAYA1050		OCHAYA1050		1401
+lep9261			MACH_LEP9261		LEP9261			1402
+svenmeb			MACH_SVENMEB		SVENMEB			1403
+fortunet2ne		MACH_FORTUNET2NE	FORTUNET2NE		1404
+nxhx			MACH_NXHX		NXHX			1406
 realview_pb11mp		MACH_REALVIEW_PB11MP	REALVIEW_PB11MP		1407
+ids500			MACH_IDS500		IDS500			1408
+ors_n725		MACH_ORS_N725		ORS_N725		1409
+hsdarm			MACH_HSDARM		HSDARM			1410
+sha_pon003		MACH_SHA_PON003		SHA_PON003		1411
+sha_pon004		MACH_SHA_PON004		SHA_PON004		1412
+sha_pon007		MACH_SHA_PON007		SHA_PON007		1413
+sha_pon011		MACH_SHA_PON011		SHA_PON011		1414
+h6042			MACH_H6042		H6042			1415
+h6043			MACH_H6043		H6043			1416
+looxc550		MACH_LOOXC550		LOOXC550		1417
+cnty_titan		MACH_CNTY_TITAN		CNTY_TITAN		1418
+app3xx			MACH_APP3XX		APP3XX			1419
+sideoatsgrama		MACH_SIDEOATSGRAMA	SIDEOATSGRAMA		1420
+treo700p		MACH_TREO700P		TREO700P		1421
+treo700w		MACH_TREO700W		TREO700W		1422
+treo750			MACH_TREO750		TREO750			1423
+treo755p		MACH_TREO755P		TREO755P		1424
+ezreganut9200		MACH_EZREGANUT9200	EZREGANUT9200		1425
+sarge			MACH_SARGE		SARGE			1426
+a696			MACH_A696		A696			1427
+turtle1916		MACH_TURTLE		TURTLE			1428
 mx27_3ds		MACH_MX27_3DS		MX27_3DS		1430
+bishop			MACH_BISHOP		BISHOP			1431
+pxx			MACH_PXX		PXX			1432
+redwood			MACH_REDWOOD		REDWOOD			1433
+omap_2430dlp		MACH_OMAP_2430DLP	OMAP_2430DLP		1436
+omap_2430osk		MACH_OMAP_2430OSK	OMAP_2430OSK		1437
+sardine			MACH_SARDINE		SARDINE			1438
 halibut			MACH_HALIBUT		HALIBUT			1439
 trout			MACH_TROUT		TROUT			1440
+goldfish		MACH_GOLDFISH		GOLDFISH		1441
+gesbc2440		MACH_GESBC2440		GESBC2440		1442
+nomad			MACH_NOMAD		NOMAD			1443
+rosalind		MACH_ROSALIND		ROSALIND		1444
+cc9p9215		MACH_CC9P9215		CC9P9215		1445
+cc9p9210		MACH_CC9P9210		CC9P9210		1446
+cc9p9215js		MACH_CC9P9215JS		CC9P9215JS		1447
+cc9p9210js		MACH_CC9P9210JS		CC9P9210JS		1448
+nasffe			MACH_NASFFE		NASFFE			1449
+tn2x0bd			MACH_TN2X0BD		TN2X0BD			1450
+gwmpxa			MACH_GWMPXA		GWMPXA			1451
+exyplus			MACH_EXYPLUS		EXYPLUS			1452
+jadoo21			MACH_JADOO21		JADOO21			1453
+looxn560		MACH_LOOXN560		LOOXN560		1454
+bonsai			MACH_BONSAI		BONSAI			1455
+adsmilgato		MACH_ADSMILGATO		ADSMILGATO		1456
+gba			MACH_GBA		GBA			1457
+h6044			MACH_H6044		H6044			1458
+app			MACH_APP		APP			1459
 tct_hammer		MACH_TCT_HAMMER		TCT_HAMMER		1460
 herald			MACH_HERALD		HERALD			1461
+artemis			MACH_ARTEMIS		ARTEMIS			1462
+htctitan		MACH_HTCTITAN		HTCTITAN		1463
+qranium			MACH_QRANIUM		QRANIUM			1464
+adx_wsc2		MACH_ADX_WSC2		ADX_WSC2		1465
+adx_medcom		MACH_ADX_MEDCOM		ADX_MEDCOM		1466
+bboard			MACH_BBOARD		BBOARD			1467
+cambria			MACH_CAMBRIA		CAMBRIA			1468
+mt7xxx			MACH_MT7XXX		MT7XXX			1469
+matrix512		MACH_MATRIX512		MATRIX512		1470
+matrix522		MACH_MATRIX522		MATRIX522		1471
+ipac5010		MACH_IPAC5010		IPAC5010		1472
+sakura			MACH_SAKURA		SAKURA			1473
+grocx			MACH_GROCX		GROCX			1474
+pm9263			MACH_PM9263		PM9263			1475
 sim_one			MACH_SIM_ONE		SIM_ONE			1476
+acq132			MACH_ACQ132		ACQ132			1477
+datr			MACH_DATR		DATR			1478
+actux1			MACH_ACTUX1		ACTUX1			1479
+actux2			MACH_ACTUX2		ACTUX2			1480
+actux3			MACH_ACTUX3		ACTUX3			1481
+flexit			MACH_FLEXIT		FLEXIT			1482
+bh2x0bd			MACH_BH2X0BD		BH2X0BD			1483
+atb2002			MACH_ATB2002		ATB2002			1484
+xenon			MACH_XENON		XENON			1485
+fm607			MACH_FM607		FM607			1486
+matrix514		MACH_MATRIX514		MATRIX514		1487
+matrix524		MACH_MATRIX524		MATRIX524		1488
+inpod			MACH_INPOD		INPOD			1489
 jive			MACH_JIVE		JIVE			1490
+tll_mx21		MACH_TLL_MX21		TLL_MX21		1491
+sbc2800			MACH_SBC2800		SBC2800			1492
+cc7ucamry		MACH_CC7UCAMRY		CC7UCAMRY		1493
+ubisys_p9_sc15		MACH_UBISYS_P9_SC15	UBISYS_P9_SC15		1494
+ubisys_p9_ssc2d10	MACH_UBISYS_P9_SSC2D10	UBISYS_P9_SSC2D10	1495
+ubisys_p9_rcu3		MACH_UBISYS_P9_RCU3	UBISYS_P9_RCU3		1496
+aml_m8000		MACH_AML_M8000		AML_M8000		1497
+snapper_270		MACH_SNAPPER_270	SNAPPER_270		1498
+omap_bbx		MACH_OMAP_BBX		OMAP_BBX		1499
+ucn2410			MACH_UCN2410		UCN2410			1500
 sam9_l9260		MACH_SAM9_L9260		SAM9_L9260		1501
+eti_c2			MACH_ETI_C2		ETI_C2			1502
+avalanche		MACH_AVALANCHE		AVALANCHE		1503
 realview_pb1176		MACH_REALVIEW_PB1176	REALVIEW_PB1176		1504
+dp1500			MACH_DP1500		DP1500			1505
+apple_iphone		MACH_APPLE_IPHONE	APPLE_IPHONE		1506
 yl9200			MACH_YL9200		YL9200			1507
 rd88f5182		MACH_RD88F5182		RD88F5182		1508
 kurobox_pro		MACH_KUROBOX_PRO	KUROBOX_PRO		1509
+se_poet			MACH_SE_POET		SE_POET			1510
 mx31_3ds		MACH_MX31_3DS		MX31_3DS		1511
+r270			MACH_R270		R270			1512
+armour21		MACH_ARMOUR21		ARMOUR21		1513
+dt2			MACH_DT2		DT2			1514
+vt4			MACH_VT4		VT4			1515
+tyco320			MACH_TYCO320		TYCO320			1516
+adma			MACH_ADMA		ADMA			1517
+wp188			MACH_WP188		WP188			1518
+corsica			MACH_CORSICA		CORSICA			1519
+bigeye			MACH_BIGEYE		BIGEYE			1520
+tll5000			MACH_TLL5000		TLL5000			1522
+bebot			MACH_BEBOT		BEBOT			1523
 qong			MACH_QONG		QONG			1524
+tcompact		MACH_TCOMPACT		TCOMPACT		1525
+puma5			MACH_PUMA5		PUMA5			1526
+elara			MACH_ELARA		ELARA			1527
+ellington		MACH_ELLINGTON		ELLINGTON		1528
+xda_atom		MACH_XDA_ATOM		XDA_ATOM		1529
+energizer2		MACH_ENERGIZER2		ENERGIZER2		1530
+odin			MACH_ODIN		ODIN			1531
+actux4			MACH_ACTUX4		ACTUX4			1532
+esl_omap		MACH_ESL_OMAP		ESL_OMAP		1533
 omap2evm		MACH_OMAP2EVM		OMAP2EVM		1534
 omap3evm		MACH_OMAP3EVM		OMAP3EVM		1535
+adx_pcu57		MACH_ADX_PCU57		ADX_PCU57		1536
+monaco			MACH_MONACO		MONACO			1537
+levante			MACH_LEVANTE		LEVANTE			1538
+tmxipx425		MACH_TMXIPX425		TMXIPX425		1539
+leep			MACH_LEEP		LEEP			1540
+raad			MACH_RAAD		RAAD			1541
 dns323			MACH_DNS323		DNS323			1542
+ap1000			MACH_AP1000		AP1000			1543
+a9sam6432		MACH_A9SAM6432		A9SAM6432		1544
+shiny			MACH_SHINY		SHINY			1545
 omap3_beagle		MACH_OMAP3_BEAGLE	OMAP3_BEAGLE		1546
+csr_bdb2		MACH_CSR_BDB2		CSR_BDB2		1547
 nokia_n810		MACH_NOKIA_N810		NOKIA_N810		1548
+c270			MACH_C270		C270			1549
+sentry			MACH_SENTRY		SENTRY			1550
 pcm038			MACH_PCM038		PCM038			1551
+anc300			MACH_ANC300		ANC300			1552
+htckaiser		MACH_HTCKAISER		HTCKAISER		1553
+sbat100			MACH_SBAT100		SBAT100			1554
+modunorm		MACH_MODUNORM		MODUNORM		1555
+pelos_twarm		MACH_PELOS_TWARM	PELOS_TWARM		1556
+flank			MACH_FLANK		FLANK			1557
+sirloin			MACH_SIRLOIN		SIRLOIN			1558
+brisket			MACH_BRISKET		BRISKET			1559
+chuck			MACH_CHUCK		CHUCK			1560
+otter			MACH_OTTER		OTTER			1561
+davinci_ldk		MACH_DAVINCI_LDK	DAVINCI_LDK		1562
+phreedom		MACH_PHREEDOM		PHREEDOM		1563
+sg310			MACH_SG310		SG310			1564
 ts209			MACH_TS209		TS209			1565
 at91cap9adk		MACH_AT91CAP9ADK	AT91CAP9ADK		1566
+tion9315		MACH_TION9315		TION9315		1567
+mast			MACH_MAST		MAST			1568
+pfw			MACH_PFW		PFW			1569
+yl_p2440		MACH_YL_P2440		YL_P2440		1570
+zsbc32			MACH_ZSBC32		ZSBC32			1571
+omap_pace2		MACH_OMAP_PACE2		OMAP_PACE2		1572
+imx_pace2		MACH_IMX_PACE2		IMX_PACE2		1573
 mx31moboard		MACH_MX31MOBOARD	MX31MOBOARD		1574
+mx37_3ds		MACH_MX37_3DS		MX37_3DS		1575
+rcc			MACH_RCC		RCC			1576
+dmp			MACH_ARM9		ARM9			1577
 vision_ep9307		MACH_VISION_EP9307	VISION_EP9307		1578
+scly1000		MACH_SCLY1000		SCLY1000		1579
+fontel_ep		MACH_FONTEL_EP		FONTEL_EP		1580
+voiceblue3g		MACH_VOICEBLUE3G	VOICEBLUE3G		1581
+tt9200			MACH_TT9200		TT9200			1582
+digi2410		MACH_DIGI2410		DIGI2410		1583
 terastation_pro2	MACH_TERASTATION_PRO2	TERASTATION_PRO2	1584
 linkstation_pro		MACH_LINKSTATION_PRO	LINKSTATION_PRO		1585
+motorola_a780		MACH_MOTOROLA_A780	MOTOROLA_A780		1587
+motorola_e6		MACH_MOTOROLA_E6	MOTOROLA_E6		1588
+motorola_e2		MACH_MOTOROLA_E2	MOTOROLA_E2		1589
+motorola_e680		MACH_MOTOROLA_E680	MOTOROLA_E680		1590
+ur2410			MACH_UR2410		UR2410			1591
+tas9261			MACH_TAS9261		TAS9261			1592
+davinci_hermes_hd	MACH_HERMES_HD		HERMES_HD		1593
+davinci_perseo_hd	MACH_PERSEO_HD		PERSEO_HD		1594
+stargazer2		MACH_STARGAZER2		STARGAZER2		1595
 e350			MACH_E350		E350			1596
+wpcm450			MACH_WPCM450		WPCM450			1597
+cartesio		MACH_CARTESIO		CARTESIO		1598
+toybox			MACH_TOYBOX		TOYBOX			1599
+tx27			MACH_TX27		TX27			1600
 ts409			MACH_TS409		TS409			1601
+p300			MACH_P300		P300			1602
+xdacomet		MACH_XDACOMET		XDACOMET		1603
+dexflex2		MACH_DEXFLEX2		DEXFLEX2		1604
+ow			MACH_OW			OW			1605
+armebs3			MACH_ARMEBS3		ARMEBS3			1606
+u3			MACH_U3			U3			1607
+smdk2450		MACH_SMDK2450		SMDK2450		1608
 rsi_ews			MACH_RSI_EWS		RSI_EWS			1609
+tnb			MACH_TNB		TNB			1610
+toepath			MACH_TOEPATH		TOEPATH			1611
+kb9263			MACH_KB9263		KB9263			1612
+mt7108			MACH_MT7108		MT7108			1613
+smtr2440		MACH_SMTR2440		SMTR2440		1614
+manao			MACH_MANAO		MANAO			1615
 cm_x300			MACH_CM_X300		CM_X300			1616
+gulfstream_kp		MACH_GULFSTREAM_KP	GULFSTREAM_KP		1617
+lanreadyfn522		MACH_LANREADYFN522	LANREADYFN522		1618
+arma37			MACH_ARMA37		ARMA37			1619
+mendel			MACH_MENDEL		MENDEL			1620
+pelco_iliad		MACH_PELCO_ILIAD	PELCO_ILIAD		1621
+unit2p			MACH_UNIT2P		UNIT2P			1622
+inc20otter		MACH_INC20OTTER		INC20OTTER		1623
 at91sam9g20ek		MACH_AT91SAM9G20EK	AT91SAM9G20EK		1624
+sc_ge2			MACH_STORCENTER		STORCENTER		1625
 smdk6410		MACH_SMDK6410		SMDK6410		1626
 u300			MACH_U300		U300			1627
+u500			MACH_U500		U500			1628
+ds9260			MACH_DS9260		DS9260			1629
+riverrock		MACH_RIVERROCK		RIVERROCK		1630
+scibath			MACH_SCIBATH		SCIBATH			1631
+at91sam7se		MACH_AT91SAM7SE512EK	AT91SAM7SE512EK		1632
 wrt350n_v2		MACH_WRT350N_V2		WRT350N_V2		1633
+multimedia		MACH_MULTIMEDIA		MULTIMEDIA		1634
+marvin			MACH_MARVIN		MARVIN			1635
+x500			MACH_X500		X500			1636
+awlug4lcu		MACH_AWLUG4LCU		AWLUG4LCU		1637
+palermoc		MACH_PALERMOC		PALERMOC		1638
 omap_ldp		MACH_OMAP_LDP		OMAP_LDP		1639
+ip500			MACH_IP500		IP500			1640
+ase2			MACH_ASE2		ASE2			1642
+mx35evb			MACH_MX35EVB		MX35EVB			1643
+aml_m8050		MACH_AML_M8050		AML_M8050		1644
 mx35_3ds		MACH_MX35_3DS		MX35_3DS		1645
+mars			MACH_MARS		MARS			1646
 neuros_osd2		MACH_NEUROS_OSD2	NEUROS_OSD2		1647
+badger			MACH_BADGER		BADGER			1648
 trizeps4wl		MACH_TRIZEPS4WL		TRIZEPS4WL		1649
+trizeps5		MACH_TRIZEPS5		TRIZEPS5		1650
+marlin			MACH_MARLIN		MARLIN			1651
 ts78xx			MACH_TS78XX		TS78XX			1652
+hpipaq214		MACH_HPIPAQ214		HPIPAQ214		1653
+at572d940dcm		MACH_AT572D940DCM	AT572D940DCM		1654
+ne1board		MACH_NE1BOARD		NE1BOARD		1655
+zante			MACH_ZANTE		ZANTE			1656
 sffsdr			MACH_SFFSDR		SFFSDR			1657
+tw2662			MACH_TW2662		TW2662			1658
+vf10xx			MACH_VF10XX		VF10XX			1659
+zoran43xx		MACH_ZORAN43XX		ZORAN43XX		1660
+sonix926		MACH_SONIX926		SONIX926		1661
+celestialsemi		MACH_CELESTIALSEMI	CELESTIALSEMI		1662
+cc9m2443js		MACH_CC9M2443JS		CC9M2443JS		1663
+tw5334			MACH_TW5334		TW5334			1664
+omap_htcartemis		MACH_HTCARTEMIS		HTCARTEMIS		1665
+nal_hlite		MACH_NAL_HLITE		NAL_HLITE		1666
+htcvogue		MACH_HTCVOGUE		HTCVOGUE		1667
+smartweb		MACH_SMARTWEB		SMARTWEB		1668
+mv86xx			MACH_MV86XX		MV86XX			1669
+mv87xx			MACH_MV87XX		MV87XX			1670
+songyoungho		MACH_SONGYOUNGHO	SONGYOUNGHO		1671
+younghotema		MACH_YOUNGHOTEMA	YOUNGHOTEMA		1672
 pcm037			MACH_PCM037		PCM037			1673
+mmvp			MACH_MMVP		MMVP			1674
+mmap			MACH_MMAP		MMAP			1675
+ptid2410		MACH_PTID2410		PTID2410		1676
+james_926		MACH_JAMES_926		JAMES_926		1677
+fm6000			MACH_FM6000		FM6000			1678
 db88f6281_bp		MACH_DB88F6281_BP	DB88F6281_BP		1680
 rd88f6192_nas		MACH_RD88F6192_NAS	RD88F6192_NAS		1681
 rd88f6281		MACH_RD88F6281		RD88F6281		1682
 db78x00_bp		MACH_DB78X00_BP		DB78X00_BP		1683
 smdk2416		MACH_SMDK2416		SMDK2416		1685
+oce_spider_si		MACH_OCE_SPIDER_SI	OCE_SPIDER_SI		1686
+oce_spider_sk		MACH_OCE_SPIDER_SK	OCE_SPIDER_SK		1687
+rovern6			MACH_ROVERN6		ROVERN6			1688
+pelco_evolution		MACH_PELCO_EVOLUTION	PELCO_EVOLUTION		1689
 wbd111			MACH_WBD111		WBD111			1690
+elaracpe		MACH_ELARACPE		ELARACPE		1691
+mabv3			MACH_MABV3		MABV3			1692
 mv2120			MACH_MV2120		MV2120			1693
+csb737			MACH_CSB737		CSB737			1695
 mx51_3ds		MACH_MX51_3DS		MX51_3DS		1696
+g900			MACH_G900		G900			1697
+apf27			MACH_APF27		APF27			1698
+ggus2000		MACH_GGUS2000		GGUS2000		1699
+omap_2430_mimic		MACH_OMAP_2430_MIMIC	OMAP_2430_MIMIC		1700
 imx27lite		MACH_IMX27LITE		IMX27LITE		1701
+almex			MACH_ALMEX		ALMEX			1702
+control			MACH_CONTROL		CONTROL			1703
+mba2410			MACH_MBA2410		MBA2410			1704
+volcano			MACH_VOLCANO		VOLCANO			1705
+zenith			MACH_ZENITH		ZENITH			1706
+muchip			MACH_MUCHIP		MUCHIP			1707
+magellan		MACH_MAGELLAN		MAGELLAN		1708
 usb_a9260		MACH_USB_A9260		USB_A9260		1709
 usb_a9263		MACH_USB_A9263		USB_A9263		1710
 qil_a9260		MACH_QIL_A9260		QIL_A9260		1711
+cme9210			MACH_CME9210		CME9210			1712
+hczh4			MACH_HCZH4		HCZH4			1713
+spearbasic		MACH_SPEARBASIC		SPEARBASIC		1714
+dep2440			MACH_DEP2440		DEP2440			1715
+hdl_gxr			MACH_HDL_GXR		HDL_GXR			1716
+hdl_gt			MACH_HDL_GT		HDL_GT			1717
+hdl_4g			MACH_HDL_4G		HDL_4G			1718
+s3c6000			MACH_S3C6000		S3C6000			1719
+mmsp2_mdk		MACH_MMSP2_MDK		MMSP2_MDK		1720
+mpx220			MACH_MPX220		MPX220			1721
 kzm_arm11_01		MACH_KZM_ARM11_01	KZM_ARM11_01		1722
+htc_polaris		MACH_HTC_POLARIS	HTC_POLARIS		1723
+htc_kaiser		MACH_HTC_KAISER		HTC_KAISER		1724
+lg_ks20			MACH_LG_KS20		LG_KS20			1725
+hhgps			MACH_HHGPS		HHGPS			1726
 nokia_n810_wimax	MACH_NOKIA_N810_WIMAX	NOKIA_N810_WIMAX	1727
+insight			MACH_INSIGHT		INSIGHT			1728
 sapphire		MACH_SAPPHIRE		SAPPHIRE		1729
+csb637xo		MACH_CSB637XO		CSB637XO		1730
+evisiong		MACH_EVISIONG		EVISIONG		1731
 stmp37xx		MACH_STMP37XX		STMP37XX		1732
 stmp378x		MACH_STMP378X		STMP378X		1733
+tnt			MACH_TNT		TNT			1734
+tbxt			MACH_TBXT		TBXT			1735
+playmate		MACH_PLAYMATE		PLAYMATE		1736
+pns10			MACH_PNS10		PNS10			1737
+eznavi			MACH_EZNAVI		EZNAVI			1738
+ps4000			MACH_PS4000		PS4000			1739
 ezx_a780		MACH_EZX_A780		EZX_A780		1740
 ezx_e680		MACH_EZX_E680		EZX_E680		1741
 ezx_a1200		MACH_EZX_A1200		EZX_A1200		1742
 ezx_e6			MACH_EZX_E6		EZX_E6			1743
 ezx_e2			MACH_EZX_E2		EZX_E2			1744
 ezx_a910		MACH_EZX_A910		EZX_A910		1745
+cwmx31			MACH_CWMX31		CWMX31			1746
+sl2312			MACH_SL2312		SL2312			1747
+blenny			MACH_BLENNY		BLENNY			1748
+ds107			MACH_DS107		DS107			1749
+dsx07			MACH_DSX07		DSX07			1750
+picocom1		MACH_PICOCOM1		PICOCOM1		1751
+lynx_wolverine		MACH_LYNX_WOLVERINE	LYNX_WOLVERINE		1752
+ubisys_p9_sc19		MACH_UBISYS_P9_SC19	UBISYS_P9_SC19		1753
+kratos_low		MACH_KRATOS_LOW		KRATOS_LOW		1754
+m700			MACH_M700		M700			1755
 edmini_v2		MACH_EDMINI_V2		EDMINI_V2		1756
 zipit2			MACH_ZIPIT2		ZIPIT2			1757
+hslfemtocell		MACH_HSLFEMTOCELL	HSLFEMTOCELL		1758
+daintree_at91		MACH_DAINTREE_AT91	DAINTREE_AT91		1759
+sg560usb		MACH_SG560USB		SG560USB		1760
 omap3_pandora		MACH_OMAP3_PANDORA	OMAP3_PANDORA		1761
+usr8200			MACH_USR8200		USR8200			1762
+s1s65k			MACH_S1S65K		S1S65K			1763
+s2s65a			MACH_S2S65A		S2S65A			1764
+icore			MACH_ICORE		ICORE			1765
 mss2			MACH_MSS2		MSS2			1766
+belmont			MACH_BELMONT		BELMONT			1767
+asusp525		MACH_ASUSP525		ASUSP525		1768
 lb88rc8480		MACH_LB88RC8480		LB88RC8480		1769
+hipxa			MACH_HIPXA		HIPXA			1770
 mx25_3ds		MACH_MX25_3DS		MX25_3DS		1771
+m800			MACH_M800		M800			1772
 omap3530_lv_som		MACH_OMAP3530_LV_SOM	OMAP3530_LV_SOM		1773
+prima_evb		MACH_PRIMA_EVB		PRIMA_EVB		1774
+mx31bt1			MACH_MX31BT1		MX31BT1			1775
+atlas4_evb		MACH_ATLAS4_EVB		ATLAS4_EVB		1776
+mx31cicada		MACH_MX31CICADA		MX31CICADA		1777
+mi424wr			MACH_MI424WR		MI424WR			1778
+axs_ultrax		MACH_AXS_ULTRAX		AXS_ULTRAX		1779
+at572d940deb		MACH_AT572D940DEB	AT572D940DEB		1780
 davinci_da830_evm	MACH_DAVINCI_DA830_EVM	DAVINCI_DA830_EVM	1781
+ep9302			MACH_EP9302		EP9302			1782
+at572d940hfek		MACH_AT572D940HFEB	AT572D940HFEB		1783
+cybook3			MACH_CYBOOK3		CYBOOK3			1784
+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
+vandihud		MACH_VANDIHUD		VANDIHUD		1790
+magx_e8			MACH_MAGX_E8		MAGX_E8			1791
+magx_z6			MACH_MAGX_Z6		MAGX_Z6			1792
+magx_v8			MACH_MAGX_V8		MAGX_V8			1793
+magx_u9			MACH_MAGX_U9		MAGX_U9			1794
+toughcf08		MACH_TOUGHCF08		TOUGHCF08		1795
+zw4400			MACH_ZW4400		ZW4400			1796
+marat91			MACH_MARAT91		MARAT91			1797
 overo			MACH_OVERO		OVERO			1798
 at2440evb		MACH_AT2440EVB		AT2440EVB		1799
 neocore926		MACH_NEOCORE926		NEOCORE926		1800
 wnr854t			MACH_WNR854T		WNR854T			1801
+imx27			MACH_IMX27		IMX27			1802
+moose_db		MACH_MOOSE_DB		MOOSE_DB		1803
+fab4			MACH_FAB4		FAB4			1804
+htcdiamond		MACH_HTCDIAMOND		HTCDIAMOND		1805
+fiona			MACH_FIONA		FIONA			1806
+mxc30030_x		MACH_MXC30030_X		MXC30030_X		1807
+bmp1000			MACH_BMP1000		BMP1000			1808
+logi9200		MACH_LOGI9200		LOGI9200		1809
+tqma31			MACH_TQMA31		TQMA31			1810
+ccw9p9215js		MACH_CCW9P9215JS	CCW9P9215JS		1811
 rd88f5181l_ge		MACH_RD88F5181L_GE	RD88F5181L_GE		1812
+sifmain			MACH_SIFMAIN		SIFMAIN			1813
+sam9_l9261		MACH_SAM9_L9261		SAM9_L9261		1814
+cc9m2443		MACH_CC9M2443		CC9M2443		1815
+xaria300		MACH_XARIA300		XARIA300		1816
+it9200			MACH_IT9200		IT9200			1817
 rd88f5181l_fxo		MACH_RD88F5181L_FXO	RD88F5181L_FXO		1818
+kriss_sensor		MACH_KRISS_SENSOR	KRISS_SENSOR		1819
+pilz_pmi5		MACH_PILZ_PMI5		PILZ_PMI5		1820
+jade			MACH_JADE		JADE			1821
+ks8695_softplc		MACH_KS8695_SOFTPLC	KS8695_SOFTPLC		1822
+gprisc3			MACH_GPRISC3		GPRISC3			1823
 stamp9g20		MACH_STAMP9G20		STAMP9G20		1824
+smdk6430		MACH_SMDK6430		SMDK6430		1825
 smdkc100		MACH_SMDKC100		SMDKC100		1826
 tavorevb		MACH_TAVOREVB		TAVOREVB		1827
 saar			MACH_SAAR		SAAR			1828
+deister_eyecam		MACH_DEISTER_EYECAM	DEISTER_EYECAM		1829
 at91sam9m10g45ek	MACH_AT91SAM9M10G45EK	AT91SAM9M10G45EK	1830
+linkstation_produo	MACH_LINKSTATION_PRODUO	LINKSTATION_PRODUO	1831
+hit_b0			MACH_HIT_B0		HIT_B0			1832
+adx_rmu			MACH_ADX_RMU		ADX_RMU			1833
+xg_cpe_main		MACH_XG_CPE_MAIN	XG_CPE_MAIN		1834
+edb9407a		MACH_EDB9407A		EDB9407A		1835
+dtb9608			MACH_DTB9608		DTB9608			1836
+em104v1			MACH_EM104V1		EM104V1			1837
+demo			MACH_DEMO		DEMO			1838
+logi9260		MACH_LOGI9260		LOGI9260		1839
+mx31_exm32		MACH_MX31_EXM32		MX31_EXM32		1840
 usb_a9g20		MACH_USB_A9G20		USB_A9G20		1841
+picproje2008		MACH_PICPROJE2008	PICPROJE2008		1842
+cs_e9315		MACH_CS_E9315		CS_E9315		1843
+qil_a9g20		MACH_QIL_A9G20		QIL_A9G20		1844
+sha_pon020		MACH_SHA_PON020		SHA_PON020		1845
+nad			MACH_NAD		NAD			1846
+sbc35_a9260		MACH_SBC35_A9260	SBC35_A9260		1847
+sbc35_a9g20		MACH_SBC35_A9G20	SBC35_A9G20		1848
+davinci_beginning	MACH_DAVINCI_BEGINNING	DAVINCI_BEGINNING	1849
+uwc			MACH_UWC		UWC			1850
 mxlads			MACH_MXLADS		MXLADS			1851
+htcnike			MACH_HTCNIKE		HTCNIKE			1852
+deister_pxa270		MACH_DEISTER_PXA270	DEISTER_PXA270		1853
+cme9210js		MACH_CME9210JS		CME9210JS		1854
+cc9p9360		MACH_CC9P9360		CC9P9360		1855
+mocha			MACH_MOCHA		MOCHA			1856
+wapd170ag		MACH_WAPD170AG		WAPD170AG		1857
 linkstation_mini	MACH_LINKSTATION_MINI	LINKSTATION_MINI	1858
 afeb9260		MACH_AFEB9260		AFEB9260		1859
+w90x900			MACH_W90X900		W90X900			1860
+w90x700			MACH_W90X700		W90X700			1861
+kt300ip			MACH_KT300IP		KT300IP			1862
+kt300ip_g20		MACH_KT300IP_G20	KT300IP_G20		1863
+srcm			MACH_SRCM		SRCM			1864
+wlnx_9260		MACH_WLNX_9260		WLNX_9260		1865
+openmoko_gta03		MACH_OPENMOKO_GTA03	OPENMOKO_GTA03		1866
+osprey2			MACH_OSPREY2		OSPREY2			1867
+kbio9260		MACH_KBIO9260		KBIO9260		1868
+ginza			MACH_GINZA		GINZA			1869
+a636n			MACH_A636N		A636N			1870
 imx27ipcam		MACH_IMX27IPCAM		IMX27IPCAM		1871
+nemoc			MACH_NEMOC		NEMOC			1872
+geneva			MACH_GENEVA		GENEVA			1873
+htcpharos		MACH_HTCPHAROS		HTCPHAROS		1874
+neonc			MACH_NEONC		NEONC			1875
+nas7100			MACH_NAS7100		NAS7100			1876
+teuphone		MACH_TEUPHONE		TEUPHONE		1877
+annax_eth2		MACH_ANNAX_ETH2		ANNAX_ETH2		1878
+csb733			MACH_CSB733		CSB733			1879
+bk3			MACH_BK3		BK3			1880
+omap_em32		MACH_OMAP_EM32		OMAP_EM32		1881
+et9261cp		MACH_ET9261CP		ET9261CP		1882
+jasperc			MACH_JASPERC		JASPERC			1883
+issi_arm9		MACH_ISSI_ARM9		ISSI_ARM9		1884
+ued			MACH_UED		UED			1885
+esiblade		MACH_ESIBLADE		ESIBLADE		1886
+eye02			MACH_EYE02		EYE02			1887
+imx27kbd		MACH_IMX27KBD		IMX27KBD		1888
+kixvp435		MACH_KIXVP435		KIXVP435		1890
+kixnp435		MACH_KIXNP435		KIXNP435		1891
+africa			MACH_AFRICA		AFRICA			1892
+nh233			MACH_NH233		NH233			1893
 rd88f6183ap_ge		MACH_RD88F6183AP_GE	RD88F6183AP_GE		1894
+bcm4760			MACH_BCM4760		BCM4760			1895
+eddy_v2			MACH_EDDY_V2		EDDY_V2			1896
 realview_pba8		MACH_REALVIEW_PBA8	REALVIEW_PBA8		1897
+hid_a7			MACH_HID_A7		HID_A7			1898
+hero			MACH_HERO		HERO			1899
+omap_poseidon		MACH_OMAP_POSEIDON	OMAP_POSEIDON		1900
 realview_pbx		MACH_REALVIEW_PBX	REALVIEW_PBX		1901
 micro9s			MACH_MICRO9S		MICRO9S			1902
+mako			MACH_MAKO		MAKO			1903
+xdaflame		MACH_XDAFLAME		XDAFLAME		1904
+phidget_sbc2		MACH_PHIDGET_SBC2	PHIDGET_SBC2		1905
+limestone		MACH_LIMESTONE		LIMESTONE		1906
+iprobe_c32		MACH_IPROBE_C32		IPROBE_C32		1907
 rut100			MACH_RUT100		RUT100			1908
+asusp535		MACH_ASUSP535		ASUSP535		1909
+htcraphael		MACH_HTCRAPHAEL		HTCRAPHAEL		1910
+sygdg1			MACH_SYGDG1		SYGDG1			1911
+sygdg2			MACH_SYGDG2		SYGDG2			1912
+seoul			MACH_SEOUL		SEOUL			1913
+salerno			MACH_SALERNO		SALERNO			1914
+ucn_s3c64xx		MACH_UCN_S3C64XX	UCN_S3C64XX		1915
+msm7201a		MACH_MSM7201A		MSM7201A		1916
+lpr1			MACH_LPR1		LPR1			1917
+armadillo500fx		MACH_ARMADILLO500FX	ARMADILLO500FX		1918
 g3evm			MACH_G3EVM		G3EVM			1919
+z3_dm355		MACH_Z3_DM355		Z3_DM355		1920
 w90p910evb		MACH_W90P910EVB		W90P910EVB		1921
+w90p920evb		MACH_W90P920EVB		W90P920EVB		1922
 w90p950evb		MACH_W90P950EVB		W90P950EVB		1923
 w90n960evb		MACH_W90N960EVB		W90N960EVB		1924
+camhd			MACH_CAMHD		CAMHD			1925
+mvc100			MACH_MVC100		MVC100			1926
+electrum_200		MACH_ELECTRUM_200	ELECTRUM_200		1927
+htcjade			MACH_HTCJADE		HTCJADE			1928
+memphis			MACH_MEMPHIS		MEMPHIS			1929
+imx27sbc		MACH_IMX27SBC		IMX27SBC		1930
+lextar			MACH_LEXTAR		LEXTAR			1931
 mv88f6281gtw_ge		MACH_MV88F6281GTW_GE	MV88F6281GTW_GE		1932
 ncp			MACH_NCP		NCP			1933
+z32an_series		MACH_Z32AN		Z32AN			1934
+tmq_capd		MACH_TMQ_CAPD		TMQ_CAPD		1935
+omap3_wl		MACH_OMAP3_WL		OMAP3_WL		1936
+chumby			MACH_CHUMBY		CHUMBY			1937
+atsarm9			MACH_ATSARM9		ATSARM9			1938
 davinci_dm365_evm	MACH_DAVINCI_DM365_EVM	DAVINCI_DM365_EVM	1939
+bahamas			MACH_BAHAMAS		BAHAMAS			1940
+das			MACH_DAS		DAS			1941
+minidas			MACH_MINIDAS		MINIDAS			1942
+vk1000			MACH_VK1000		VK1000			1943
 centro			MACH_CENTRO		CENTRO			1944
+ctera_2bay		MACH_CTERA_2BAY		CTERA_2BAY		1945
+edgeconnect		MACH_EDGECONNECT	EDGECONNECT		1946
+nd27000			MACH_ND27000		ND27000			1947
+cobra			MACH_GEMALTO_COBRA	GEMALTO_COBRA		1948
+ingelabs_comet		MACH_INGELABS_COMET	INGELABS_COMET		1949
+pollux_wiz		MACH_POLLUX_WIZ		POLLUX_WIZ		1950
+blackstone		MACH_BLACKSTONE		BLACKSTONE		1951
+topaz			MACH_TOPAZ		TOPAZ			1952
+aixle			MACH_AIXLE		AIXLE			1953
+mw998			MACH_MW998		MW998			1954
 nokia_rx51		MACH_NOKIA_RX51		NOKIA_RX51		1955
+vsc5605ev		MACH_VSC5605EV		VSC5605EV		1956
+nt98700dk		MACH_NT98700DK		NT98700DK		1957
+icontact		MACH_ICONTACT		ICONTACT		1958
+swarco_frcpu		MACH_SWARCO_FRCPU	SWARCO_FRCPU		1959
+swarco_scpu		MACH_SWARCO_SCPU	SWARCO_SCPU		1960
+bbox_p16		MACH_BBOX_P16		BBOX_P16		1961
+bstd			MACH_BSTD		BSTD			1962
+sbc2440ii		MACH_SBC2440II		SBC2440II		1963
+pcm034			MACH_PCM034		PCM034			1964
+neso			MACH_NESO		NESO			1965
+wlnx_9g20		MACH_WLNX_9G20		WLNX_9G20		1966
 omap_zoom2		MACH_OMAP_ZOOM2		OMAP_ZOOM2		1967
+totemnova		MACH_TOTEMNOVA		TOTEMNOVA		1968
+c5000			MACH_C5000		C5000			1969
+unipo_at91sam9263	MACH_UNIPO_AT91SAM9263	UNIPO_AT91SAM9263	1970
+ethernut5		MACH_ETHERNUT5		ETHERNUT5		1971
+arm11			MACH_ARM11		ARM11			1972
 cpuat9260		MACH_CPUAT9260		CPUAT9260		1973
+cpupxa255		MACH_CPUPXA255		CPUPXA255		1974
 eukrea_cpuimx27		MACH_EUKREA_CPUIMX27	EUKREA_CPUIMX27		1975
+cheflux			MACH_CHEFLUX		CHEFLUX			1976
+eb_cpux9k2		MACH_EB_CPUX9K2		EB_CPUX9K2		1977
+opcotec			MACH_OPCOTEC		OPCOTEC			1978
+yt			MACH_YT			YT			1979
+motoq			MACH_MOTOQ		MOTOQ			1980
+bsb1			MACH_BSB1		BSB1			1981
 acs5k			MACH_ACS5K		ACS5K			1982
+milan			MACH_MILAN		MILAN			1983
+quartzv2		MACH_QUARTZV2		QUARTZV2		1984
+rsvp			MACH_RSVP		RSVP			1985
+rmp200			MACH_RMP200		RMP200			1986
 snapper_9260		MACH_SNAPPER_9260	SNAPPER_9260		1987
 dsm320			MACH_DSM320		DSM320			1988
+adsgcm			MACH_ADSGCM		ADSGCM			1989
+ase2_400		MACH_ASE2_400		ASE2_400		1990
+pizza			MACH_PIZZA		PIZZA			1991
+spot_ngpl		MACH_SPOT_NGPL		SPOT_NGPL		1992
+armata			MACH_ARMATA		ARMATA			1993
 exeda			MACH_EXEDA		EXEDA			1994
+mx31sf005		MACH_MX31SF005		MX31SF005		1995
+f5d8231_4_v2		MACH_F5D8231_4_V2	F5D8231_4_V2		1996
+q2440			MACH_Q2440		Q2440			1997
+qq2440			MACH_QQ2440		QQ2440			1998
 mini2440		MACH_MINI2440		MINI2440		1999
 colibri300		MACH_COLIBRI300		COLIBRI300		2000
+jades			MACH_JADES		JADES			2001
+spark			MACH_SPARK		SPARK			2002
+benzina			MACH_BENZINA		BENZINA			2003
+blaze			MACH_BLAZE		BLAZE			2004
 linkstation_ls_hgl	MACH_LINKSTATION_LS_HGL	LINKSTATION_LS_HGL	2005
+htckovsky		MACH_HTCKOVSKY		HTCKOVSKY		2006
+sony_prs505		MACH_SONY_PRS505	SONY_PRS505		2007
+hanlin_v3		MACH_HANLIN_V3		HANLIN_V3		2008
+sapphira		MACH_SAPPHIRA		SAPPHIRA		2009
+dack_sda_01		MACH_DACK_SDA_01	DACK_SDA_01		2010
+armbox			MACH_ARMBOX		ARMBOX			2011
+harris_rvp		MACH_HARRIS_RVP		HARRIS_RVP		2012
+ribaldo			MACH_RIBALDO		RIBALDO			2013
+agora			MACH_AGORA		AGORA			2014
+omap3_mini		MACH_OMAP3_MINI		OMAP3_MINI		2015
+a9sam6432_b		MACH_A9SAM6432_B	A9SAM6432_B		2016
+usg2410			MACH_USG2410		USG2410			2017
+pc72052_i10_revb	MACH_PC72052_I10_REVB	PC72052_I10_REVB	2018
+mx35_exm32		MACH_MX35_EXM32		MX35_EXM32		2019
+topas910		MACH_TOPAS910		TOPAS910		2020
+hyena			MACH_HYENA		HYENA			2021
+pospax			MACH_POSPAX		POSPAX			2022
+hdl_gx			MACH_HDL_GX		HDL_GX			2023
+ctera_4bay		MACH_CTERA_4BAY		CTERA_4BAY		2024
+ctera_plug_c		MACH_CTERA_PLUG_C	CTERA_PLUG_C		2025
+crwea_plug_i		MACH_CRWEA_PLUG_I	CRWEA_PLUG_I		2026
+egauge2			MACH_EGAUGE2		EGAUGE2			2027
+didj			MACH_DIDJ		DIDJ			2028
+m_s3c2443		MACH_MEISTER		MEISTER			2029
+htcblackstone		MACH_HTCBLACKSTONE	HTCBLACKSTONE		2030
 cpuat9g20		MACH_CPUAT9G20		CPUAT9G20		2031
 smdk6440		MACH_SMDK6440		SMDK6440		2032
+omap_35xx_mvp		MACH_OMAP_35XX_MVP	OMAP_35XX_MVP		2033
+ctera_plug_i		MACH_CTERA_PLUG_I	CTERA_PLUG_I		2034
+pvg610_100		MACH_PVG610		PVG610			2035
+hprw6815		MACH_HPRW6815		HPRW6815		2036
+omap3_oswald		MACH_OMAP3_OSWALD	OMAP3_OSWALD		2037
 nas4220b		MACH_NAS4220B		NAS4220B		2038
+htcraphael_cdma		MACH_HTCRAPHAEL_CDMA	HTCRAPHAEL_CDMA		2039
+htcdiamond_cdma		MACH_HTCDIAMOND_CDMA	HTCDIAMOND_CDMA		2040
+scaler			MACH_SCALER		SCALER			2041
 zylonite2		MACH_ZYLONITE2		ZYLONITE2		2042
 aspenite		MACH_ASPENITE		ASPENITE		2043
+teton			MACH_TETON		TETON			2044
 ttc_dkb			MACH_TTC_DKB		TTC_DKB			2045
+bishop2			MACH_BISHOP2		BISHOP2			2046
+ippv5			MACH_IPPV5		IPPV5			2047
+farm926			MACH_FARM926		FARM926			2048
+mmccpu			MACH_MMCCPU		MMCCPU			2049
+sgmsfl			MACH_SGMSFL		SGMSFL			2050
+tt8000			MACH_TT8000		TT8000			2051
+zrn4300lp		MACH_ZRN4300LP		ZRN4300LP		2052
+mptc			MACH_MPTC		MPTC			2053
+h6051			MACH_H6051		H6051			2054
+pvg610_101		MACH_PVG610_101		PVG610_101		2055
+stamp9261_pc_evb	MACH_STAMP9261_PC_EVB	STAMP9261_PC_EVB	2056
+pelco_odysseus		MACH_PELCO_ODYSSEUS	PELCO_ODYSSEUS		2057
+tny_a9260		MACH_TNY_A9260		TNY_A9260		2058
+tny_a9g20		MACH_TNY_A9G20		TNY_A9G20		2059
+aesop_mp2530f		MACH_AESOP_MP2530F	AESOP_MP2530F		2060
+dx900			MACH_DX900		DX900			2061
+cpodc2			MACH_CPODC2		CPODC2			2062
+tilt_8925		MACH_TILT_8925		TILT_8925		2063
+davinci_dm357_evm	MACH_DAVINCI_DM357_EVM	DAVINCI_DM357_EVM	2064
+swordfish		MACH_SWORDFISH		SWORDFISH		2065
+corvus			MACH_CORVUS		CORVUS			2066
+taurus			MACH_TAURUS		TAURUS			2067
+axm			MACH_AXM		AXM			2068
+axc			MACH_AXC		AXC			2069
+baby			MACH_BABY		BABY			2070
+mp200			MACH_MP200		MP200			2071
 pcm043			MACH_PCM043		PCM043			2072
+hanlin_v3c		MACH_HANLIN_V3C		HANLIN_V3C		2073
+kbk9g20			MACH_KBK9G20		KBK9G20			2074
+adsturbog5		MACH_ADSTURBOG5		ADSTURBOG5		2075
+avenger_lite1		MACH_AVENGER_LITE1	AVENGER_LITE1		2076
+suc82x			MACH_SUC		SUC			2077
+at91sam7s256		MACH_AT91SAM7S256	AT91SAM7S256		2078
+mendoza			MACH_MENDOZA		MENDOZA			2079
+kira			MACH_KIRA		KIRA			2080
+mx1hbm			MACH_MX1HBM		MX1HBM			2081
+quatro43xx		MACH_QUATRO43XX		QUATRO43XX		2082
+quatro4230		MACH_QUATRO4230		QUATRO4230		2083
+nsb400			MACH_NSB400		NSB400			2084
+drp255			MACH_DRP255		DRP255			2085
+thoth			MACH_THOTH		THOTH			2086
+firestone		MACH_FIRESTONE		FIRESTONE		2087
+asusp750		MACH_ASUSP750		ASUSP750		2088
+ctera_dl		MACH_CTERA_DL		CTERA_DL		2089
+socr			MACH_SOCR		SOCR			2090
+htcoxygen		MACH_HTCOXYGEN		HTCOXYGEN		2091
+heroc			MACH_HEROC		HEROC			2092
+zeno6800		MACH_ZENO6800		ZENO6800		2093
+sc2mcs			MACH_SC2MCS		SC2MCS			2094
+gene100			MACH_GENE100		GENE100			2095
+as353x			MACH_AS353X		AS353X			2096
 sheevaplug		MACH_SHEEVAPLUG		SHEEVAPLUG		2097
+at91sam9g20		MACH_AT91SAM9G20	AT91SAM9G20		2098
+mv88f6192gtw_fe		MACH_MV88F6192GTW_FE	MV88F6192GTW_FE		2099
+cc9200			MACH_CC9200		CC9200			2100
+sm9200			MACH_SM9200		SM9200			2101
+tp9200			MACH_TP9200		TP9200			2102
+snapperdv		MACH_SNAPPERDV		SNAPPERDV		2103
 avengers_lite		MACH_AVENGERS_LITE	AVENGERS_LITE		2104
+avengers_lite1		MACH_AVENGERS_LITE1	AVENGERS_LITE1		2105
+omap3axon		MACH_OMAP3AXON		OMAP3AXON		2106
+ma8xx			MACH_MA8XX		MA8XX			2107
+mp201ek			MACH_MP201EK		MP201EK			2108
+davinci_tux		MACH_DAVINCI_TUX	DAVINCI_TUX		2109
+mpa1600			MACH_MPA1600		MPA1600			2110
+pelco_troy		MACH_PELCO_TROY		PELCO_TROY		2111
+nsb667			MACH_NSB667		NSB667			2112
+rovers5_4mpix		MACH_ROVERS5_4MPIX	ROVERS5_4MPIX		2113
+twocom			MACH_TWOCOM		TWOCOM			2114
+ubisys_p9_rcu3r2	MACH_UBISYS_P9_RCU3R2	UBISYS_P9_RCU3R2	2115
+hero_espresso		MACH_HERO_ESPRESSO	HERO_ESPRESSO		2116
+afeusb			MACH_AFEUSB		AFEUSB			2117
+t830			MACH_T830		T830			2118
+spd8020_cc		MACH_SPD8020_CC		SPD8020_CC		2119
+om_3d7k			MACH_OM_3D7K		OM_3D7K			2120
+picocom2		MACH_PICOCOM2		PICOCOM2		2121
+uwg4mx27		MACH_UWG4MX27		UWG4MX27		2122
+uwg4mx31		MACH_UWG4MX31		UWG4MX31		2123
+cherry			MACH_CHERRY		CHERRY			2124
 mx51_babbage		MACH_MX51_BABBAGE	MX51_BABBAGE		2125
+s3c2440turkiye		MACH_S3C2440TURKIYE	S3C2440TURKIYE		2126
 tx37			MACH_TX37		TX37			2127
+sbc2800_9g20		MACH_SBC2800_9G20	SBC2800_9G20		2128
+benzglb			MACH_BENZGLB		BENZGLB			2129
+benztd			MACH_BENZTD		BENZTD			2130
+cartesio_plus		MACH_CARTESIO_PLUS	CARTESIO_PLUS		2131
+solrad_g20		MACH_SOLRAD_G20		SOLRAD_G20		2132
+mx27wallace		MACH_MX27WALLACE	MX27WALLACE		2133
+fmzwebmodul		MACH_FMZWEBMODUL	FMZWEBMODUL		2134
 rd78x00_masa		MACH_RD78X00_MASA	RD78X00_MASA		2135
+smallogger		MACH_SMALLOGGER		SMALLOGGER		2136
+ccw9p9215		MACH_CCW9P9215		CCW9P9215		2137
 dm355_leopard		MACH_DM355_LEOPARD	DM355_LEOPARD		2138
 ts219			MACH_TS219		TS219			2139
+tny_a9263		MACH_TNY_A9263		TNY_A9263		2140
+apollo			MACH_APOLLO		APOLLO			2141
+at91cap9stk		MACH_AT91CAP9STK	AT91CAP9STK		2142
+spc300			MACH_SPC300		SPC300			2143
+eko			MACH_EKO		EKO			2144
+ccw9m2443		MACH_CCW9M2443		CCW9M2443		2145
+ccw9m2443js		MACH_CCW9M2443JS	CCW9M2443JS		2146
+m2m_router_device	MACH_M2M_ROUTER_DEVICE	M2M_ROUTER_DEVICE	2147
+str9104nas		MACH_STAR9104NAS	STAR9104NAS		2148
 pca100			MACH_PCA100		PCA100			2149
+z3_dm365_mod_01		MACH_Z3_DM365_MOD_01	Z3_DM365_MOD_01		2150
+hipox			MACH_HIPOX		HIPOX			2151
+omap3_piteds		MACH_OMAP3_PITEDS	OMAP3_PITEDS		2152
+bm150r			MACH_BM150R		BM150R			2153
+tbone			MACH_TBONE		TBONE			2154
+merlin			MACH_MERLIN		MERLIN			2155
+falcon			MACH_FALCON		FALCON			2156
 davinci_da850_evm	MACH_DAVINCI_DA850_EVM	DAVINCI_DA850_EVM	2157
+s5p6440			MACH_S5P6440		S5P6440			2158
 at91sam9g10ek		MACH_AT91SAM9G10EK	AT91SAM9G10EK		2159
 omap_4430sdp		MACH_OMAP_4430SDP	OMAP_4430SDP		2160
+lpc313x			MACH_LPC313X		LPC313X			2161
 magx_zn5		MACH_MAGX_ZN5		MAGX_ZN5		2162
+magx_em30		MACH_MAGX_EM30		MAGX_EM30		2163
+magx_ve66		MACH_MAGX_VE66		MAGX_VE66		2164
+meesc			MACH_MEESC		MEESC			2165
+otc570			MACH_OTC570		OTC570			2166
+bcu2412			MACH_BCU2412		BCU2412			2167
+beacon			MACH_BEACON		BEACON			2168
+actia_tgw		MACH_ACTIA_TGW		ACTIA_TGW		2169
+e4430			MACH_E4430		E4430			2170
+ql300			MACH_QL300		QL300			2171
 btmavb101		MACH_BTMAVB101		BTMAVB101		2172
 btmawb101		MACH_BTMAWB101		BTMAWB101		2173
+sq201			MACH_SQ201		SQ201			2174
+quatro45xx		MACH_QUATRO45XX		QUATRO45XX		2175
+openpad			MACH_OPENPAD		OPENPAD			2176
 tx25			MACH_TX25		TX25			2177
 omap3_torpedo		MACH_OMAP3_TORPEDO	OMAP3_TORPEDO		2178
+htcraphael_k		MACH_HTCRAPHAEL_K	HTCRAPHAEL_K		2179
+lal43			MACH_LAL43		LAL43			2181
+htcraphael_cdma500	MACH_HTCRAPHAEL_CDMA500	HTCRAPHAEL_CDMA500	2182
 anw6410			MACH_ANW6410		ANW6410			2183
+htcprophet		MACH_HTCPROPHET		HTCPROPHET		2185
+cfa_10022		MACH_CFA_10022		CFA_10022		2186
 imx27_visstrim_m10	MACH_IMX27_VISSTRIM_M10	IMX27_VISSTRIM_M10	2187
+px2imx27		MACH_PX2IMX27		PX2IMX27		2188
+stm3210e_eval		MACH_STM3210E_EVAL	STM3210E_EVAL		2189
+dvs10			MACH_DVS10		DVS10			2190
 portuxg20		MACH_PORTUXG20		PORTUXG20		2191
+arm_spv			MACH_ARM_SPV		ARM_SPV			2192
 smdkc110		MACH_SMDKC110		SMDKC110		2193
+cabespresso		MACH_CABESPRESSO	CABESPRESSO		2194
+hmc800			MACH_HMC800		HMC800			2195
+sholes			MACH_SHOLES		SHOLES			2196
+btmxc31			MACH_BTMXC31		BTMXC31			2197
+dt501			MACH_DT501		DT501			2198
+ktx			MACH_KTX		KTX			2199
 omap3517evm		MACH_OMAP3517EVM	OMAP3517EVM		2200
 netspace_v2		MACH_NETSPACE_V2	NETSPACE_V2		2201
 netspace_max_v2		MACH_NETSPACE_MAX_V2	NETSPACE_MAX_V2		2202
 d2net_v2		MACH_D2NET_V2		D2NET_V2		2203
 net2big_v2		MACH_NET2BIG_V2		NET2BIG_V2		2204
+net4big_v2		MACH_NET4BIG_V2		NET4BIG_V2		2205
 net5big_v2		MACH_NET5BIG_V2		NET5BIG_V2		2206
+endb2443		MACH_ENDB2443		ENDB2443		2207
 inetspace_v2		MACH_INETSPACE_V2	INETSPACE_V2		2208
+tros			MACH_TROS		TROS			2209
+pelco_homer		MACH_PELCO_HOMER	PELCO_HOMER		2210
+ofsp8			MACH_OFSP8		OFSP8			2211
 at91sam9g45ekes		MACH_AT91SAM9G45EKES	AT91SAM9G45EKES		2212
+guf_cupid		MACH_GUF_CUPID		GUF_CUPID		2213
+eab1r			MACH_EAB1R		EAB1R			2214
+desirec			MACH_DESIREC		DESIREC			2215
+cordoba			MACH_CORDOBA		CORDOBA			2216
+irvine			MACH_IRVINE		IRVINE			2217
+sff772			MACH_SFF772		SFF772			2218
+pelco_milano		MACH_PELCO_MILANO	PELCO_MILANO		2219
 pc7302			MACH_PC7302		PC7302			2220
+bip6000			MACH_BIP6000		BIP6000			2221
+silvermoon		MACH_SILVERMOON		SILVERMOON		2222
+vc0830			MACH_VC0830		VC0830			2223
+dt430			MACH_DT430		DT430			2224
+ji42pf			MACH_JI42PF		JI42PF			2225
+gnet_ksm		MACH_GNET_KSM		GNET_KSM		2226
+gnet_sgm		MACH_GNET_SGM		GNET_SGM		2227
+gnet_sgr		MACH_GNET_SGR		GNET_SGR		2228
+omap3_icetekevm		MACH_OMAP3_ICETEKEVM	OMAP3_ICETEKEVM		2229
+pnp			MACH_PNP		PNP			2230
+ctera_2bay_k		MACH_CTERA_2BAY_K	CTERA_2BAY_K		2231
+ctera_2bay_u		MACH_CTERA_2BAY_U	CTERA_2BAY_U		2232
+sas_c			MACH_SAS_C		SAS_C			2233
+vma2315			MACH_VMA2315		VMA2315			2234
+vcs			MACH_VCS		VCS			2235
 spear600		MACH_SPEAR600		SPEAR600		2236
 spear300		MACH_SPEAR300		SPEAR300		2237
+spear1300		MACH_SPEAR1300		SPEAR1300		2238
 lilly1131		MACH_LILLY1131		LILLY1131		2239
+arvoo_ax301		MACH_ARVOO_AX301	ARVOO_AX301		2240
+mapphone		MACH_MAPPHONE		MAPPHONE		2241
+legend			MACH_LEGEND		LEGEND			2242
+salsa			MACH_SALSA		SALSA			2243
+lounge			MACH_LOUNGE		LOUNGE			2244
+vision			MACH_VISION		VISION			2245
+vmb20			MACH_VMB20		VMB20			2246
+hy2410			MACH_HY2410		HY2410			2247
+hy9315			MACH_HY9315		HY9315			2248
+bullwinkle		MACH_BULLWINKLE		BULLWINKLE		2249
+arm_ultimator2		MACH_ARM_ULTIMATOR2	ARM_ULTIMATOR2		2250
+vs_v210			MACH_VS_V210		VS_V210			2252
+vs_v212			MACH_VS_V212		VS_V212			2253
 hmt			MACH_HMT		HMT			2254
+km_kirkwood		MACH_KM_KIRKWOOD	KM_KIRKWOOD		2255
+vesper			MACH_VESPER		VESPER			2256
+str9			MACH_STR9		STR9			2257
+omap3_wl_ff		MACH_OMAP3_WL_FF	OMAP3_WL_FF		2258
+simcom			MACH_SIMCOM		SIMCOM			2259
+mcwebio			MACH_MCWEBIO		MCWEBIO			2260
+omap3_phrazer		MACH_OMAP3_PHRAZER	OMAP3_PHRAZER		2261
+darwin			MACH_DARWIN		DARWIN			2262
+oratiscomu		MACH_ORATISCOMU		ORATISCOMU		2263
+rtsbc20			MACH_RTSBC20		RTSBC20			2264
+sgh_i780		MACH_I780		I780			2265
+gemini324		MACH_GEMINI324		GEMINI324		2266
+oratislan		MACH_ORATISLAN		ORATISLAN		2267
+oratisalog		MACH_ORATISALOG		ORATISALOG		2268
+oratismadi		MACH_ORATISMADI		ORATISMADI		2269
+oratisot16		MACH_ORATISOT16		ORATISOT16		2270
+oratisdesk		MACH_ORATISDESK		ORATISDESK		2271
 vexpress		MACH_VEXPRESS		VEXPRESS		2272
+sintexo			MACH_SINTEXO		SINTEXO			2273
+cm3389			MACH_CM3389		CM3389			2274
+omap3_cio		MACH_OMAP3_CIO		OMAP3_CIO		2275
+sgh_i900		MACH_SGH_I900		SGH_I900		2276
+bst100			MACH_BST100		BST100			2277
+passion			MACH_PASSION		PASSION			2278
+indesign_at91sam	MACH_INDESIGN_AT91SAM	INDESIGN_AT91SAM	2279
+c4_badger		MACH_C4_BADGER		C4_BADGER		2280
+c4_viper		MACH_C4_VIPER		C4_VIPER		2281
 d2net			MACH_D2NET		D2NET			2282
 bigdisk			MACH_BIGDISK		BIGDISK			2283
+notalvision		MACH_NOTALVISION	NOTALVISION		2284
+omap3_kboc		MACH_OMAP3_KBOC		OMAP3_KBOC		2285
+cyclone			MACH_CYCLONE		CYCLONE			2286
+ninja			MACH_NINJA		NINJA			2287
 at91sam9g20ek_2mmc	MACH_AT91SAM9G20EK_2MMC	AT91SAM9G20EK_2MMC	2288
 bcmring			MACH_BCMRING		BCMRING			2289
+resol_dl2		MACH_RESOL_DL2		RESOL_DL2		2290
+ifosw			MACH_IFOSW		IFOSW			2291
+htcrhodium		MACH_HTCRHODIUM		HTCRHODIUM		2292
+htctopaz		MACH_HTCTOPAZ		HTCTOPAZ		2293
+matrix504		MACH_MATRIX504		MATRIX504		2294
+mrfsa			MACH_MRFSA		MRFSA			2295
+sc_p270			MACH_SC_P270		SC_P270			2296
+atlas5_evb		MACH_ATLAS5_EVB		ATLAS5_EVB		2297
+pelco_lobox		MACH_PELCO_LOBOX	PELCO_LOBOX		2298
+dilax_pcu200		MACH_DILAX_PCU200	DILAX_PCU200		2299
+leonardo		MACH_LEONARDO		LEONARDO		2300
+zoran_approach7		MACH_ZORAN_APPROACH7	ZORAN_APPROACH7		2301
 dp6xx			MACH_DP6XX		DP6XX			2302
+bcm2153_vesper		MACH_BCM2153_VESPER	BCM2153_VESPER		2303
 mahimahi		MACH_MAHIMAHI		MAHIMAHI		2304
+clickc			MACH_CLICKC		CLICKC			2305
+zb_gateway		MACH_ZB_GATEWAY		ZB_GATEWAY		2306
+tazcard			MACH_TAZCARD		TAZCARD			2307
+tazdev			MACH_TAZDEV		TAZDEV			2308
+annax_cb_arm		MACH_ANNAX_CB_ARM	ANNAX_CB_ARM		2309
+annax_dm3		MACH_ANNAX_DM3		ANNAX_DM3		2310
+cerebric		MACH_CEREBRIC		CEREBRIC		2311
+orca			MACH_ORCA		ORCA			2312
+pc9260			MACH_PC9260		PC9260			2313
+ems285a			MACH_EMS285A		EMS285A			2314
+gec2410			MACH_GEC2410		GEC2410			2315
+gec2440			MACH_GEC2440		GEC2440			2316
+mw903			MACH_ARCH_MW903		ARCH_MW903		2317
+mw2440			MACH_MW2440		MW2440			2318
+ecac2378		MACH_ECAC2378		ECAC2378		2319
+tazkiosk		MACH_TAZKIOSK		TAZKIOSK		2320
+whiterabbit_mch		MACH_WHITERABBIT_MCH	WHITERABBIT_MCH		2321
+sbox9263		MACH_SBOX9263		SBOX9263		2322
 smdk6442		MACH_SMDK6442		SMDK6442		2324
 openrd_base		MACH_OPENRD_BASE	OPENRD_BASE		2325
+incredible		MACH_INCREDIBLE		INCREDIBLE		2326
+incrediblec		MACH_INCREDIBLEC	INCREDIBLEC		2327
+heroct			MACH_HEROCT		HEROCT			2328
+mmnet1000		MACH_MMNET1000		MMNET1000		2329
 devkit8000		MACH_DEVKIT8000		DEVKIT8000		2330
+devkit9000		MACH_DEVKIT9000		DEVKIT9000		2331
+mx31txtr		MACH_MX31TXTR		MX31TXTR		2332
+u380			MACH_U380		U380			2333
+oamp3_hualu		MACH_HUALU_BOARD	HUALU_BOARD		2334
+npcmx50			MACH_NPCMX50		NPCMX50			2335
 mx51_efikamx		MACH_MX51_EFIKAMX	MX51_EFIKAMX		2336
+mx51_lange52		MACH_MX51_LANGE52	MX51_LANGE52		2337
+riom			MACH_RIOM		RIOM			2338
+comcas			MACH_COMCAS		COMCAS			2339
+wsi_mx27		MACH_WSI_MX27		WSI_MX27		2340
 cm_t35			MACH_CM_T35		CM_T35			2341
 net2big			MACH_NET2BIG		NET2BIG			2342
+motorola_a1600		MACH_MOTOROLA_A1600	MOTOROLA_A1600		2343
 igep0020		MACH_IGEP0020		IGEP0020		2344
+igep0010		MACH_IGEP0010		IGEP0010		2345
+mv6281gtwge2		MACH_MV6281GTWGE2	MV6281GTWGE2		2346
+scat100			MACH_SCAT100		SCAT100			2347
+sanmina			MACH_SANMINA		SANMINA			2348
+momento			MACH_MOMENTO		MOMENTO			2349
+nuc9xx			MACH_NUC9XX		NUC9XX			2350
+nuc910evb		MACH_NUC910EVB		NUC910EVB		2351
+nuc920evb		MACH_NUC920EVB		NUC920EVB		2352
+nuc950evb		MACH_NUC950EVB		NUC950EVB		2353
+nuc945evb		MACH_NUC945EVB		NUC945EVB		2354
+nuc960evb		MACH_NUC960EVB		NUC960EVB		2355
 nuc932evb		MACH_NUC932EVB		NUC932EVB		2356
+nuc900			MACH_NUC900		NUC900			2357
+sd1soc			MACH_SD1SOC		SD1SOC			2358
+ln2440bc		MACH_LN2440BC		LN2440BC		2359
+rsbc			MACH_RSBC		RSBC			2360
 openrd_client		MACH_OPENRD_CLIENT	OPENRD_CLIENT		2361
+hpipaq11x		MACH_HPIPAQ11X		HPIPAQ11X		2362
+wayland			MACH_WAYLAND		WAYLAND			2363
+acnbsx102		MACH_ACNBSX102		ACNBSX102		2364
+hwat91			MACH_HWAT91		HWAT91			2365
+at91sam9263cs		MACH_AT91SAM9263CS	AT91SAM9263CS		2366
+csb732			MACH_CSB732		CSB732			2367
 u8500			MACH_U8500		U8500			2368
+huqiu			MACH_HUQIU		HUQIU			2369
 mx51_efikasb		MACH_MX51_EFIKASB	MX51_EFIKASB		2370
+pmt1g			MACH_PMT1G		PMT1G			2371
+htcelf			MACH_HTCELF		HTCELF			2372
+armadillo420		MACH_ARMADILLO420	ARMADILLO420		2373
+armadillo440		MACH_ARMADILLO440	ARMADILLO440		2374
+u_chip_dual_arm		MACH_U_CHIP_DUAL_ARM	U_CHIP_DUAL_ARM		2375
+csr_bdb3		MACH_CSR_BDB3		CSR_BDB3		2376
+dolby_cat1018		MACH_DOLBY_CAT1018	DOLBY_CAT1018		2377
+hy9307			MACH_HY9307		HY9307			2378
+aspire_easystore	MACH_A_ES		A_ES			2379
+davinci_irif		MACH_DAVINCI_IRIF	DAVINCI_IRIF		2380
+agama9263		MACH_AGAMA9263		AGAMA9263		2381
 marvell_jasper		MACH_MARVELL_JASPER	MARVELL_JASPER		2382
 flint			MACH_FLINT		FLINT			2383
 tavorevb3		MACH_TAVOREVB3		TAVOREVB3		2384
+sch_m490		MACH_SCH_M490		SCH_M490		2386
+rbl01			MACH_RBL01		RBL01			2387
+omnifi			MACH_OMNIFI		OMNIFI			2388
+otavalo			MACH_OTAVALO		OTAVALO			2389
+htc_excalibur_s620	MACH_HTC_EXCALIBUR_S620	HTC_EXCALIBUR_S620	2391
+htc_opal		MACH_HTC_OPAL		HTC_OPAL		2392
 touchbook		MACH_TOUCHBOOK		TOUCHBOOK		2393
+latte			MACH_LATTE		LATTE			2394
+xa200			MACH_XA200		XA200			2395
+nimrod			MACH_NIMROD		NIMROD			2396
+cc9p9215_3g		MACH_CC9P9215_3G	CC9P9215_3G		2397
+cc9p9215_3gjs		MACH_CC9P9215_3GJS	CC9P9215_3GJS		2398
+tk71			MACH_TK71		TK71			2399
+comham3525		MACH_COMHAM3525		COMHAM3525		2400
+mx31erebus		MACH_MX31EREBUS		MX31EREBUS		2401
+mcardmx27		MACH_MCARDMX27		MCARDMX27		2402
+paradise		MACH_PARADISE		PARADISE		2403
+tide			MACH_TIDE		TIDE			2404
+wzl2440			MACH_WZL2440		WZL2440			2405
+sdrdemo			MACH_SDRDEMO		SDRDEMO			2406
+ethercan2		MACH_ETHERCAN2		ETHERCAN2		2407
+ecmimg20		MACH_ECMIMG20		ECMIMG20		2408
+omap_dragon		MACH_OMAP_DRAGON	OMAP_DRAGON		2409
+halo			MACH_HALO		HALO			2410
+huangshan		MACH_HUANGSHAN		HUANGSHAN		2411
+vl_ma2sc		MACH_VL_MA2SC		VL_MA2SC		2412
 raumfeld_rc		MACH_RAUMFELD_RC	RAUMFELD_RC		2413
 raumfeld_connector	MACH_RAUMFELD_CONNECTOR	RAUMFELD_CONNECTOR	2414
 raumfeld_speaker	MACH_RAUMFELD_SPEAKER	RAUMFELD_SPEAKER	2415
+multibus_master		MACH_MULTIBUS_MASTER	MULTIBUS_MASTER		2416
+multibus_pbk		MACH_MULTIBUS_PBK	MULTIBUS_PBK		2417
 tnetv107x		MACH_TNETV107X		TNETV107X		2418
+snake			MACH_SNAKE		SNAKE			2419
+cwmx27			MACH_CWMX27		CWMX27			2420
+sch_m480		MACH_SCH_M480		SCH_M480		2421
+platypus		MACH_PLATYPUS		PLATYPUS		2422
+pss2			MACH_PSS2		PSS2			2423
+davinci_apm150		MACH_DAVINCI_APM150	DAVINCI_APM150		2424
+str9100			MACH_STR9100		STR9100			2425
+net5big			MACH_NET5BIG		NET5BIG			2426
+seabed9263		MACH_SEABED9263		SEABED9263		2427
 mx51_m2id		MACH_MX51_M2ID		MX51_M2ID		2428
+octvocplus_eb		MACH_OCTVOCPLUS_EB	OCTVOCPLUS_EB		2429
+klk_firefox		MACH_KLK_FIREFOX	KLK_FIREFOX		2430
+klk_wirma_module	MACH_KLK_WIRMA_MODULE	KLK_WIRMA_MODULE	2431
+klk_wirma_mmi		MACH_KLK_WIRMA_MMI	KLK_WIRMA_MMI		2432
+supersonic		MACH_SUPERSONIC		SUPERSONIC		2433
+liberty			MACH_LIBERTY		LIBERTY			2434
+mh355			MACH_MH355		MH355			2435
+pc7802			MACH_PC7802		PC7802			2436
+gnet_sgc		MACH_GNET_SGC		GNET_SGC		2437
+einstein15		MACH_EINSTEIN15		EINSTEIN15		2438
+cmpd			MACH_CMPD		CMPD			2439
+davinci_hase1		MACH_DAVINCI_HASE1	DAVINCI_HASE1		2440
+lgeincitephone		MACH_LGEINCITEPHONE	LGEINCITEPHONE		2441
+ea313x			MACH_EA313X		EA313X			2442
+fwbd_39064		MACH_FWBD_39064		FWBD_39064		2443
+fwbd_390128		MACH_FWBD_390128	FWBD_390128		2444
+pelco_moe		MACH_PELCO_MOE		PELCO_MOE		2445
+minimix27		MACH_MINIMIX27		MINIMIX27		2446
+omap3_thunder		MACH_OMAP3_THUNDER	OMAP3_THUNDER		2447
+passionc		MACH_PASSIONC		PASSIONC		2448
+mx27amata		MACH_MX27AMATA		MX27AMATA		2449
+bgat1			MACH_BGAT1		BGAT1			2450
+buzz			MACH_BUZZ		BUZZ			2451
+mb9g20			MACH_MB9G20		MB9G20			2452
+yushan			MACH_YUSHAN		YUSHAN			2453
+lizard			MACH_LIZARD		LIZARD			2454
+omap3polycom		MACH_OMAP3POLYCOM	OMAP3POLYCOM		2455
 smdkv210		MACH_SMDKV210		SMDKV210		2456
+bravo			MACH_BRAVO		BRAVO			2457
+siogentoo1		MACH_SIOGENTOO1		SIOGENTOO1		2458
+siogentoo2		MACH_SIOGENTOO2		SIOGENTOO2		2459
+sm3k			MACH_SM3K		SM3K			2460
+acer_tempo_f900		MACH_ACER_TEMPO_F900	ACER_TEMPO_F900		2461
+glittertind		MACH_GLITTERTIND	GLITTERTIND		2463
 omap_zoom3		MACH_OMAP_ZOOM3		OMAP_ZOOM3		2464
 omap_3630sdp		MACH_OMAP_3630SDP	OMAP_3630SDP		2465
+cybook2440		MACH_CYBOOK2440		CYBOOK2440		2466
+torino_s		MACH_TORINO_S		TORINO_S		2467
+havana			MACH_HAVANA		HAVANA			2468
+beaumont_11		MACH_BEAUMONT_11	BEAUMONT_11		2469
+vanguard		MACH_VANGUARD		VANGUARD		2470
+s5pc110_draco		MACH_S5PC110_DRACO	S5PC110_DRACO		2471
+cartesio_two		MACH_CARTESIO_TWO	CARTESIO_TWO		2472
+aster			MACH_ASTER		ASTER			2473
+voguesv210		MACH_VOGUESV210		VOGUESV210		2474
+acm500x			MACH_ACM500X		ACM500X			2475
+km9260			MACH_KM9260		KM9260			2476
+nideflexg1		MACH_NIDEFLEXG1		NIDEFLEXG1		2477
+ctera_plug_io		MACH_CTERA_PLUG_IO	CTERA_PLUG_IO		2478
 smartq7			MACH_SMARTQ7		SMARTQ7			2479
+at91sam9g10ek2		MACH_AT91SAM9G10EK2	AT91SAM9G10EK2		2480
+asusp527		MACH_ASUSP527		ASUSP527		2481
+at91sam9g20mpm2		MACH_AT91SAM9G20MPM2	AT91SAM9G20MPM2		2482
+topasa900		MACH_TOPASA900		TOPASA900		2483
+electrum_100		MACH_ELECTRUM_100	ELECTRUM_100		2484
+mx51grb			MACH_MX51GRB		MX51GRB			2485
+xea300			MACH_XEA300		XEA300			2486
+htcstartrek		MACH_HTCSTARTREK	HTCSTARTREK		2487
+lima			MACH_LIMA		LIMA			2488
+csb740			MACH_CSB740		CSB740			2489
+usb_s8815		MACH_USB_S8815		USB_S8815		2490
 watson_efm_plugin	MACH_WATSON_EFM_PLUGIN	WATSON_EFM_PLUGIN	2491
+milkyway		MACH_MILKYWAY		MILKYWAY		2492
 g4evm			MACH_G4EVM		G4EVM			2493
+picomod6		MACH_PICOMOD6		PICOMOD6		2494
 omapl138_hawkboard	MACH_OMAPL138_HAWKBOARD	OMAPL138_HAWKBOARD	2495
+ip6000			MACH_IP6000		IP6000			2496
+ip6010			MACH_IP6010		IP6010			2497
+utm400			MACH_UTM400		UTM400			2498
+omap3_zybex		MACH_OMAP3_ZYBEX	OMAP3_ZYBEX		2499
+wireless_space		MACH_WIRELESS_SPACE	WIRELESS_SPACE		2500
+sx560			MACH_SX560		SX560			2501
 ts41x			MACH_TS41X		TS41X			2502
+elphel10373		MACH_ELPHEL10373	ELPHEL10373		2503
+rhobot			MACH_RHOBOT		RHOBOT			2504
+mx51_refresh		MACH_MX51_REFRESH	MX51_REFRESH		2505
+ls9260			MACH_LS9260		LS9260			2506
+shank			MACH_SHANK		SHANK			2507
+qsd8x50_st1		MACH_QSD8X50_ST1	QSD8X50_ST1		2508
+at91sam9m10ekes		MACH_AT91SAM9M10EKES	AT91SAM9M10EKES		2509
+hiram			MACH_HIRAM		HIRAM			2510
 phy3250			MACH_PHY3250		PHY3250			2511
+ea3250			MACH_EA3250		EA3250			2512
+fdi3250			MACH_FDI3250		FDI3250			2513
+at91sam9263nit		MACH_AT91SAM9263NIT	AT91SAM9263NIT		2515
+ccmx51			MACH_CCMX51		CCMX51			2516
+ccmx51js		MACH_CCMX51JS		CCMX51JS		2517
+ccwmx51			MACH_CCWMX51		CCWMX51			2518
+ccwmx51js		MACH_CCWMX51JS		CCWMX51JS		2519
 mini6410		MACH_MINI6410		MINI6410		2520
+tiny6410		MACH_TINY6410		TINY6410		2521
+nano6410		MACH_NANO6410		NANO6410		2522
+at572d940hfnldb		MACH_AT572D940HFNLDB	AT572D940HFNLDB		2523
+htcleo			MACH_HTCLEO		HTCLEO			2524
+avp13			MACH_AVP13		AVP13			2525
+xxsvideod		MACH_XXSVIDEOD		XXSVIDEOD		2526
+vpnext			MACH_VPNEXT		VPNEXT			2527
+swarco_itc3		MACH_SWARCO_ITC3	SWARCO_ITC3		2528
 tx51			MACH_TX51		TX51			2529
+dolby_cat1021		MACH_DOLBY_CAT1021	DOLBY_CAT1021		2530
 mx28evk			MACH_MX28EVK		MX28EVK			2531
+phoenix260		MACH_PHOENIX260		PHOENIX260		2532
+uvaca_stork		MACH_UVACA_STORK	UVACA_STORK		2533
 smartq5			MACH_SMARTQ5		SMARTQ5			2534
+all3078			MACH_ALL3078		ALL3078			2535
+ctera_2bay_ds		MACH_CTERA_2BAY_DS	CTERA_2BAY_DS		2536
+siogentoo3		MACH_SIOGENTOO3		SIOGENTOO3		2537
+epb5000			MACH_EPB5000		EPB5000			2538
+hy9263			MACH_HY9263		HY9263			2539
+acer_tempo_m900		MACH_ACER_TEMPO_M900	ACER_TEMPO_M900		2540
+acer_tempo_dx650	MACH_ACER_TEMPO_DX900	ACER_TEMPO_DX900	2541
+acer_tempo_x960		MACH_ACER_TEMPO_X960	ACER_TEMPO_X960		2542
+acer_eten_v900		MACH_ACER_ETEN_V900	ACER_ETEN_V900		2543
+acer_eten_x900		MACH_ACER_ETEN_X900	ACER_ETEN_X900		2544
+bonnell			MACH_BONNELL		BONNELL			2545
+oht_mx27		MACH_OHT_MX27		OHT_MX27		2546
+htcquartz		MACH_HTCQUARTZ		HTCQUARTZ		2547
 davinci_dm6467tevm	MACH_DAVINCI_DM6467TEVM	DAVINCI_DM6467TEVM	2548
+c3ax03			MACH_C3AX03		C3AX03			2549
 mxt_td60		MACH_MXT_TD60		MXT_TD60		2550
+esyx			MACH_ESYX		ESYX			2551
+dove_db2		MACH_DOVE_DB2		DOVE_DB2		2552
+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
+arm11_board		MACH_CS_MISANO		CS_MISANO		2572
+magnolia2		MACH_MAGNOLIA2		MAGNOLIA2		2573
+emxx			MACH_EMXX		EMXX			2574
+outlaw			MACH_OUTLAW		OUTLAW			2575
 riot_bei2		MACH_RIOT_BEI2		RIOT_BEI2		2576
+riot_gx2		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_am35xx		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
+buzzc			MACH_BUZZC		BUZZC			2596
+sasie2			MACH_SASIE2		SASIE2			2597
+smartmeter_dl		MACH_SMARTMETER_DL	SMARTMETER_DL		2599
+wzl6410			MACH_WZL6410		WZL6410			2600
+wzl6410m		MACH_WZL6410M		WZL6410M		2601
+wzl6410f		MACH_WZL6410F		WZL6410F		2602
+wzl6410i		MACH_WZL6410I		WZL6410I		2603
+spacecom1		MACH_SPACECOM1		SPACECOM1		2604
+pingu920		MACH_PINGU920		PINGU920		2605
+bravoc			MACH_BRAVOC		BRAVOC			2606
+vdssw			MACH_VDSSW		VDSSW			2608
+romulus			MACH_ROMULUS		ROMULUS			2609
+omap_magic		MACH_OMAP_MAGIC		OMAP_MAGIC		2610
+eltd100			MACH_ELTD100		ELTD100			2611
 capc7117		MACH_CAPC7117		CAPC7117		2612
+swan			MACH_SWAN		SWAN			2613
+veu			MACH_VEU		VEU			2614
+rm2			MACH_RM2		RM2			2615
+tt2100			MACH_TT2100		TT2100			2616
+venice			MACH_VENICE		VENICE			2617
+pc7323			MACH_PC7323		PC7323			2618
+masp			MACH_MASP		MASP			2619
+fujitsu_tvstbsoc0	MACH_FUJITSU_TVSTBSOC	FUJITSU_TVSTBSOC	2620
+fujitsu_tvstbsoc1	MACH_FUJITSU_TVSTBSOC1	FUJITSU_TVSTBSOC1	2621
+lexikon			MACH_LEXIKON		LEXIKON			2622
+mini2440v2		MACH_MINI2440V2		MINI2440V2		2623
 icontrol		MACH_ICONTROL		ICONTROL		2624
 gplugd			MACH_GPLUGD		GPLUGD			2625
+qsd8x50a_st1_1		MACH_QSD8X50A_ST1_1	QSD8X50A_ST1_1		2626
 qsd8x50a_st1_5		MACH_QSD8X50A_ST1_5	QSD8X50A_ST1_5		2627
+bee			MACH_BEE		BEE			2628
 mx23evk			MACH_MX23EVK		MX23EVK			2629
 ap4evb			MACH_AP4EVB		AP4EVB			2630
+stockholm		MACH_STOCKHOLM		STOCKHOLM		2631
+lpc_h3131		MACH_LPC_H3131		LPC_H3131		2632
+stingray		MACH_STINGRAY		STINGRAY		2633
+kraken			MACH_KRAKEN		KRAKEN			2634
+gw2388			MACH_GW2388		GW2388			2635
+jadecpu			MACH_JADECPU		JADECPU			2636
+carlisle		MACH_CARLISLE		CARLISLE		2637
+lux_sf9			MACH_LUX_SF9		LUX_SF9			2638
+nemid_tb		MACH_NEMID_TB		NEMID_TB		2639
+terrier			MACH_TERRIER		TERRIER			2640
+turbot			MACH_TURBOT		TURBOT			2641
+sanddab			MACH_SANDDAB		SANDDAB			2642
+mx35_cicada		MACH_MX35_CICADA	MX35_CICADA		2643
+ghi2703d		MACH_GHI2703D		GHI2703D		2644
+lux_sfx9		MACH_LUX_SFX9		LUX_SFX9		2645
+lux_sf9g		MACH_LUX_SF9G		LUX_SF9G		2646
+lux_edk9		MACH_LUX_EDK9		LUX_EDK9		2647
+hw90240			MACH_HW90240		HW90240			2648
+dm365_leopard		MACH_DM365_LEOPARD	DM365_LEOPARD		2649
 mityomapl138		MACH_MITYOMAPL138	MITYOMAPL138		2650
+scat110			MACH_SCAT110		SCAT110			2651
+acer_a1			MACH_ACER_A1		ACER_A1			2652
+cmcontrol		MACH_CMCONTROL		CMCONTROL		2653
+pelco_lamar		MACH_PELCO_LAMAR	PELCO_LAMAR		2654
+rfp43			MACH_RFP43		RFP43			2655
+sk86r0301		MACH_SK86R0301		SK86R0301		2656
+ctpxa			MACH_CTPXA		CTPXA			2657
+epb_arm9_a		MACH_EPB_ARM9_A		EPB_ARM9_A		2658
 guruplug		MACH_GURUPLUG		GURUPLUG		2659
 spear310		MACH_SPEAR310		SPEAR310		2660
 spear320		MACH_SPEAR320		SPEAR320		2661
+robotx			MACH_ROBOTX		ROBOTX			2662
+lsxhl			MACH_LSXHL		LSXHL			2663
+smartlite		MACH_SMARTLITE		SMARTLITE		2664
+cws2			MACH_CWS2		CWS2			2665
+m619			MACH_M619		M619			2666
+smartview		MACH_SMARTVIEW		SMARTVIEW		2667
+lsa_salsa		MACH_LSA_SALSA		LSA_SALSA		2668
+kizbox			MACH_KIZBOX		KIZBOX			2669
+htccharmer		MACH_HTCCHARMER		HTCCHARMER		2670
+guf_neso_lt		MACH_GUF_NESO_LT	GUF_NESO_LT		2671
+pm9g45			MACH_PM9G45		PM9G45			2672
+htcpanther		MACH_HTCPANTHER		HTCPANTHER		2673
+htcpanther_cdma		MACH_HTCPANTHER_CDMA	HTCPANTHER_CDMA		2674
+reb01			MACH_REB01		REB01			2675
 aquila			MACH_AQUILA		AQUILA			2676
+spark_sls_hw2		MACH_SPARK_SLS_HW2	SPARK_SLS_HW2		2677
 esata_sheevaplug	MACH_ESATA_SHEEVAPLUG	ESATA_SHEEVAPLUG	2678
 msm7x30_surf		MACH_MSM7X30_SURF	MSM7X30_SURF		2679
+micro2440		MACH_MICRO2440		MICRO2440		2680
+am2440			MACH_AM2440		AM2440			2681
+tq2440			MACH_TQ2440		TQ2440			2682
 ea2478devkit		MACH_EA2478DEVKIT	EA2478DEVKIT		2683
+ak880x			MACH_AK880X		AK880X			2684
+cobra3530		MACH_COBRA3530		COBRA3530		2685
+pmppb			MACH_PMPPB		PMPPB			2686
+u6715			MACH_U6715		U6715			2687
+axar1500_sender		MACH_AXAR1500_SENDER	AXAR1500_SENDER		2688
+g30_dvb			MACH_G30_DVB		G30_DVB			2689
+vc088x			MACH_VC088X		VC088X			2690
+mioa702			MACH_MIOA702		MIOA702			2691
+hpmin			MACH_HPMIN		HPMIN			2692
+ak880xak		MACH_AK880XAK		AK880XAK		2693
+arm926tomap850		MACH_ARM926TOMAP850	ARM926TOMAP850		2694
+lkevm			MACH_LKEVM		LKEVM			2695
+mw6410			MACH_MW6410		MW6410			2696
 terastation_wxl		MACH_TERASTATION_WXL	TERASTATION_WXL		2697
+cpu8000e		MACH_CPU8000E		CPU8000E		2698
+tokyo			MACH_TOKYO		TOKYO			2700
+msm7201a_surf		MACH_MSM7201A_SURF	MSM7201A_SURF		2701
+msm7201a_ffa		MACH_MSM7201A_FFA	MSM7201A_FFA		2702
 msm7x25_surf		MACH_MSM7X25_SURF	MSM7X25_SURF		2703
 msm7x25_ffa		MACH_MSM7X25_FFA	MSM7X25_FFA		2704
 msm7x27_surf		MACH_MSM7X27_SURF	MSM7X27_SURF		2705
 msm7x27_ffa		MACH_MSM7X27_FFA	MSM7X27_FFA		2706
 msm7x30_ffa		MACH_MSM7X30_FFA	MSM7X30_FFA		2707
 qsd8x50_surf		MACH_QSD8X50_SURF	QSD8X50_SURF		2708
+qsd8x50_comet		MACH_QSD8X50_COMET	QSD8X50_COMET		2709
+qsd8x50_ffa		MACH_QSD8X50_FFA	QSD8X50_FFA		2710
+qsd8x50a_surf		MACH_QSD8X50A_SURF	QSD8X50A_SURF		2711
+qsd8x50a_ffa		MACH_QSD8X50A_FFA	QSD8X50A_FFA		2712
+adx_xgcp10		MACH_ADX_XGCP10		ADX_XGCP10		2713
+mcgwumts2a		MACH_MCGWUMTS2A		MCGWUMTS2A		2714
+mobikt			MACH_MOBIKT		MOBIKT			2715
 mx53_evk		MACH_MX53_EVK		MX53_EVK		2716
 igep0030		MACH_IGEP0030		IGEP0030		2717
+axell_h40_h50_ctrl	MACH_AXELL_H40_H50_CTRL	AXELL_H40_H50_CTRL	2718
+dtcommod		MACH_DTCOMMOD		DTCOMMOD		2719
+gould			MACH_GOULD		GOULD			2720
+siberia			MACH_SIBERIA		SIBERIA			2721
 sbc3530			MACH_SBC3530		SBC3530			2722
+qarm			MACH_QARM		QARM			2723
+mips			MACH_MIPS		MIPS			2724
+mx27grb			MACH_MX27GRB		MX27GRB			2725
+sbc8100			MACH_SBC8100		SBC8100			2726
 saarb			MACH_SAARB		SAARB			2727
+omap3mini		MACH_OMAP3MINI		OMAP3MINI		2728
+cnmbook7se		MACH_CNMBOOK7SE		CNMBOOK7SE		2729
+catan			MACH_CATAN		CATAN			2730
 harmony			MACH_HARMONY		HARMONY			2731
+tonga			MACH_TONGA		TONGA			2732
+cybook_orizon		MACH_CYBOOK_ORIZON	CYBOOK_ORIZON		2733
+htcrhodiumcdma		MACH_HTCRHODIUMCDMA	HTCRHODIUMCDMA		2734
+epc_g45			MACH_EPC_G45		EPC_G45			2735
+epc_lpc3250		MACH_EPC_LPC3250	EPC_LPC3250		2736
+mxc91341evb		MACH_MXC91341EVB	MXC91341EVB		2737
+rtw1000			MACH_RTW1000		RTW1000			2738
+bobcat			MACH_BOBCAT		BOBCAT			2739
+trizeps6		MACH_TRIZEPS6		TRIZEPS6		2740
 msm7x30_fluid		MACH_MSM7X30_FLUID	MSM7X30_FLUID		2741
+nedap9263		MACH_NEDAP9263		NEDAP9263		2742
+netgear_ms2110		MACH_NETGEAR_MS2110	NETGEAR_MS2110		2743
+bmx			MACH_BMX		BMX			2744
+netstream		MACH_NETSTREAM		NETSTREAM		2745
+vpnext_rcu		MACH_VPNEXT_RCU		VPNEXT_RCU		2746
+vpnext_mpu		MACH_VPNEXT_MPU		VPNEXT_MPU		2747
+bcmring_tablet_v1	MACH_BCMRING_TABLET_V1	BCMRING_TABLET_V1	2748
+sgarm10			MACH_SGARM10		SGARM10			2749
 cm_t3517		MACH_CM_T3517		CM_T3517		2750
+dig297			MACH_OMAP3_CPS		OMAP3_CPS		2751
+axar1500_receiver	MACH_AXAR1500_RECEIVER	AXAR1500_RECEIVER	2752
 wbd222			MACH_WBD222		WBD222			2753
+mt65xx			MACH_MT65XX		MT65XX			2754
 msm8x60_surf		MACH_MSM8X60_SURF	MSM8X60_SURF		2755
 msm8x60_sim		MACH_MSM8X60_SIM	MSM8X60_SIM		2756
 tcc8000_sdk		MACH_TCC8000_SDK	TCC8000_SDK		2758
 nanos			MACH_NANOS		NANOS			2759
+stamp9g10		MACH_STAMP9G10		STAMP9G10		2760
 stamp9g45		MACH_STAMP9G45		STAMP9G45		2761
+h6053			MACH_H6053		H6053			2762
+smint01			MACH_SMINT01		SMINT01			2763
+prtlvt2			MACH_PRTLVT2		PRTLVT2			2764
+ap420			MACH_AP420		AP420			2765
+davinci_dm365_fc	MACH_DAVINCI_DM365_FC	DAVINCI_DM365_FC	2767
+msm8x55_surf		MACH_MSM8X55_SURF	MSM8X55_SURF		2768
+msm8x55_ffa		MACH_MSM8X55_FFA	MSM8X55_FFA		2769
+esl_vamana		MACH_ESL_VAMANA		ESL_VAMANA		2770
+sbc35			MACH_SBC35		SBC35			2771
+mpx6446			MACH_MPX6446		MPX6446			2772
+oreo_controller		MACH_OREO_CONTROLLER	OREO_CONTROLLER		2773
+kopin_models		MACH_KOPIN_MODELS	KOPIN_MODELS		2774
+ttc_vision2		MACH_TTC_VISION2	TTC_VISION2		2775
 cns3420vb		MACH_CNS3420VB		CNS3420VB		2776
+lpc_evo			MACH_LPC2		LPC2			2777
+olympus			MACH_OLYMPUS		OLYMPUS			2778
+vortex			MACH_VORTEX		VORTEX			2779
+s5pc200			MACH_S5PC200		S5PC200			2780
+ecucore_9263		MACH_ECUCORE_9263	ECUCORE_9263		2781
+smdkc200		MACH_SMDKC200		SMDKC200		2782
+emsiso_sx27		MACH_EMSISO_SX27	EMSISO_SX27		2783
+apx_som9g45_ek		MACH_APX_SOM9G45_EK	APX_SOM9G45_EK		2784
+songshan		MACH_SONGSHAN		SONGSHAN		2785
+tianshan		MACH_TIANSHAN		TIANSHAN		2786
+vpx500			MACH_VPX500		VPX500			2787
+am3517sam		MACH_AM3517SAM		AM3517SAM		2788
+skat91_sim508		MACH_SKAT91_SIM508	SKAT91_SIM508		2789
+skat91_s3e		MACH_SKAT91_S3E		SKAT91_S3E		2790
 omap4_panda		MACH_OMAP4_PANDA	OMAP4_PANDA		2791
+df7220			MACH_DF7220		DF7220			2792
+nemini			MACH_NEMINI		NEMINI			2793
+t8200			MACH_T8200		T8200			2794
+apf51			MACH_APF51		APF51			2795
+dr_rc_unit		MACH_DR_RC_UNIT		DR_RC_UNIT		2796
+bordeaux		MACH_BORDEAUX		BORDEAUX		2797
+catania_b		MACH_CATANIA_B		CATANIA_B		2798
+mx51_ocean		MACH_MX51_OCEAN		MX51_OCEAN		2799
 ti8168evm		MACH_TI8168EVM		TI8168EVM		2800
+neocoreomap		MACH_NEOCOREOMAP	NEOCOREOMAP		2801
+withings_wbp		MACH_WITHINGS_WBP	WITHINGS_WBP		2802
+dbps			MACH_DBPS		DBPS			2803
+pcbfp0001		MACH_PCBFP0001		PCBFP0001		2805
+speedy			MACH_SPEEDY		SPEEDY			2806
+chrysaor		MACH_CHRYSAOR		CHRYSAOR		2807
+tango			MACH_TANGO		TANGO			2808
+synology_dsx11		MACH_SYNOLOGY_DSX11	SYNOLOGY_DSX11		2809
+hanlin_v3ext		MACH_HANLIN_V3EXT	HANLIN_V3EXT		2810
+hanlin_v5		MACH_HANLIN_V5		HANLIN_V5		2811
+hanlin_v3plus		MACH_HANLIN_V3PLUS	HANLIN_V3PLUS		2812
+iriver_story		MACH_IRIVER_STORY	IRIVER_STORY		2813
+irex_iliad		MACH_IREX_ILIAD		IREX_ILIAD		2814
+irex_dr1000		MACH_IREX_DR1000	IREX_DR1000		2815
 teton_bga		MACH_TETON_BGA		TETON_BGA		2816
+snapper9g45		MACH_SNAPPER9G45	SNAPPER9G45		2817
+tam3517			MACH_TAM3517		TAM3517			2818
+pdc100			MACH_PDC100		PDC100			2819
 eukrea_cpuimx25sd	MACH_EUKREA_CPUIMX25SD	EUKREA_CPUIMX25SD	2820
 eukrea_cpuimx35sd	MACH_EUKREA_CPUIMX35SD	EUKREA_CPUIMX35SD	2821
 eukrea_cpuimx51sd	MACH_EUKREA_CPUIMX51SD	EUKREA_CPUIMX51SD	2822
 eukrea_cpuimx51		MACH_EUKREA_CPUIMX51	EUKREA_CPUIMX51		2823
+p565			MACH_P565		P565			2824
+acer_a4			MACH_ACER_A4		ACER_A4			2825
+davinci_dm368_bip	MACH_DAVINCI_DM368_BIP	DAVINCI_DM368_BIP	2826
+eshare			MACH_ESHARE		ESHARE			2827
+wlbargn			MACH_WLBARGN		WLBARGN			2829
+bm170			MACH_BM170		BM170			2830
+netspace_mini_v2	MACH_NETSPACE_MINI_V2	NETSPACE_MINI_V2	2831
+netspace_plug_v2	MACH_NETSPACE_PLUG_V2	NETSPACE_PLUG_V2	2832
+siemens_l1		MACH_SIEMENS_L1		SIEMENS_L1		2833
+elv_lcu1		MACH_ELV_LCU1		ELV_LCU1		2834
+mcu1			MACH_MCU1		MCU1			2835
+omap3_tao3530		MACH_OMAP3_TAO3530	OMAP3_TAO3530		2836
+omap3_pcutouch		MACH_OMAP3_PCUTOUCH	OMAP3_PCUTOUCH		2837
 smdkc210		MACH_SMDKC210		SMDKC210		2838
-pca102			MACH_PCA102		PCA102			2843
+omap3_braillo		MACH_OMAP3_BRAILLO	OMAP3_BRAILLO		2839
+spyplug			MACH_SPYPLUG		SPYPLUG			2840
+ginger			MACH_GINGER		GINGER			2841
+tny_t3530		MACH_TNY_T3530		TNY_T3530		2842
+pcaal1			MACH_PCAAL1		PCAAL1			2843
+spade			MACH_SPADE		SPADE			2844
+mxc25_topaz		MACH_MXC25_TOPAZ	MXC25_TOPAZ		2845
 t5325			MACH_T5325		T5325			2846
+gw2361			MACH_GW2361		GW2361			2847
+elog			MACH_ELOG		ELOG			2848
 income			MACH_INCOME		INCOME			2849
+bcm589x			MACH_BCM589X		BCM589X			2850
+etna			MACH_ETNA		ETNA			2851
+hawks			MACH_HAWKS		HAWKS			2852
+meson			MACH_MESON		MESON			2853
+xsbase255		MACH_XSBASE255		XSBASE255		2854
+pvm2030			MACH_PVM2030		PVM2030			2855
+mioa502			MACH_MIOA502		MIOA502			2856
 vvbox_sdorig2		MACH_VVBOX_SDORIG2	VVBOX_SDORIG2		2857
 vvbox_sdlite2		MACH_VVBOX_SDLITE2	VVBOX_SDLITE2		2858
 vvbox_sdpro4		MACH_VVBOX_SDPRO4	VVBOX_SDPRO4		2859
+htc_spv_m700		MACH_HTC_SPV_M700	HTC_SPV_M700		2860
 mx257sx			MACH_MX257SX		MX257SX			2861
 goni			MACH_GONI		GONI			2862
+msm8x55_svlte_ffa	MACH_MSM8X55_SVLTE_FFA	MSM8X55_SVLTE_FFA	2863
+msm8x55_svlte_surf	MACH_MSM8X55_SVLTE_SURF	MSM8X55_SVLTE_SURF	2864
+quickstep		MACH_QUICKSTEP		QUICKSTEP		2865
+dmw96			MACH_DMW96		DMW96			2866
+hammerhead		MACH_HAMMERHEAD		HAMMERHEAD		2867
+trident			MACH_TRIDENT		TRIDENT			2868
+lightning		MACH_LIGHTNING		LIGHTNING		2869
+iconnect		MACH_ICONNECT		ICONNECT		2870
+autobot			MACH_AUTOBOT		AUTOBOT			2871
+coconut			MACH_COCONUT		COCONUT			2872
+durian			MACH_DURIAN		DURIAN			2873
+cayenne			MACH_CAYENNE		CAYENNE			2874
+fuji			MACH_FUJI		FUJI			2875
+synology_6282		MACH_SYNOLOGY_6282	SYNOLOGY_6282		2876
+em1sy			MACH_EM1SY		EM1SY			2877
+m502			MACH_M502		M502			2878
+matrix518		MACH_MATRIX518		MATRIX518		2879
+tiny_gurnard		MACH_TINY_GURNARD	TINY_GURNARD		2880
+spear1310		MACH_SPEAR1310		SPEAR1310		2881
 bv07			MACH_BV07		BV07			2882
+mxt_td61		MACH_MXT_TD61		MXT_TD61		2883
 openrd_ultimate		MACH_OPENRD_ULTIMATE	OPENRD_ULTIMATE		2884
 devixp			MACH_DEVIXP		DEVIXP			2885
 miccpt			MACH_MICCPT		MICCPT			2886
 mic256			MACH_MIC256		MIC256			2887
+as1167			MACH_AS1167		AS1167			2888
+omap3_ibiza		MACH_OMAP3_IBIZA	OMAP3_IBIZA		2889
 u5500			MACH_U5500		U5500			2890
+davinci_picto		MACH_DAVINCI_PICTO	DAVINCI_PICTO		2891
+mecha			MACH_MECHA		MECHA			2892
+bubba3			MACH_BUBBA3		BUBBA3			2893
+pupitre			MACH_PUPITRE		PUPITRE			2894
+tegra_vogue		MACH_TEGRA_VOGUE	TEGRA_VOGUE		2896
+tegra_e1165		MACH_TEGRA_E1165	TEGRA_E1165		2897
+simplenet		MACH_SIMPLENET		SIMPLENET		2898
+ec4350tbm		MACH_EC4350TBM		EC4350TBM		2899
+pec_tc			MACH_PEC_TC		PEC_TC			2900
+pec_hc2			MACH_PEC_HC2		PEC_HC2			2901
+esl_mobilis_a		MACH_ESL_MOBILIS_A	ESL_MOBILIS_A		2902
+esl_mobilis_b		MACH_ESL_MOBILIS_B	ESL_MOBILIS_B		2903
+esl_wave_a		MACH_ESL_WAVE_A		ESL_WAVE_A		2904
+esl_wave_b		MACH_ESL_WAVE_B		ESL_WAVE_B		2905
+unisense_mmm		MACH_UNISENSE_MMM	UNISENSE_MMM		2906
+blueshark		MACH_BLUESHARK		BLUESHARK		2907
+e10			MACH_E10		E10			2908
+app3k_robin		MACH_APP3K_ROBIN	APP3K_ROBIN		2909
+pov15hd			MACH_POV15HD		POV15HD			2910
+stella			MACH_STELLA		STELLA			2911
 linkstation_lschl	MACH_LINKSTATION_LSCHL	LINKSTATION_LSCHL	2913
+netwalker		MACH_NETWALKER		NETWALKER		2914
+acsx106			MACH_ACSX106		ACSX106			2915
+atlas5_c1		MACH_ATLAS5_C1		ATLAS5_C1		2916
+nsb3ast			MACH_NSB3AST		NSB3AST			2917
+gnet_slc		MACH_GNET_SLC		GNET_SLC		2918
+af4000			MACH_AF4000		AF4000			2919
+ark9431			MACH_ARK9431		ARK9431			2920
+fs_s5pc100		MACH_FS_S5PC100		FS_S5PC100		2921
+omap3505nova8		MACH_OMAP3505NOVA8	OMAP3505NOVA8		2922
+omap3621_edp1		MACH_OMAP3621_EDP1	OMAP3621_EDP1		2923
+oratisaes		MACH_ORATISAES		ORATISAES		2924
 smdkv310		MACH_SMDKV310		SMDKV310		2925
+siemens_l0		MACH_SIEMENS_L0		SIEMENS_L0		2926
+ventana			MACH_VENTANA		VENTANA			2927
 wm8505_7in_netbook	MACH_WM8505_7IN_NETBOOK	WM8505_7IN_NETBOOK	2928
+ec4350sdb		MACH_EC4350SDB		EC4350SDB		2929
+mimas			MACH_MIMAS		MIMAS			2930
+titan			MACH_TITAN		TITAN			2931
 craneboard		MACH_CRANEBOARD		CRANEBOARD		2932
+es2440			MACH_ES2440		ES2440			2933
+najay_a9263		MACH_NAJAY_A9263	NAJAY_A9263		2934
+htctornado		MACH_HTCTORNADO		HTCTORNADO		2935
+dimm_mx257		MACH_DIMM_MX257		DIMM_MX257		2936
+jigen301		MACH_JIGEN		JIGEN			2937
 smdk6450		MACH_SMDK6450		SMDK6450		2938
+meno_qng		MACH_MENO_QNG		MENO_QNG		2939
+ns2416			MACH_NS2416		NS2416			2940
+rpc353			MACH_RPC353		RPC353			2941
+tq6410			MACH_TQ6410		TQ6410			2942
+sky6410			MACH_SKY6410		SKY6410			2943
+dynasty			MACH_DYNASTY		DYNASTY			2944
+vivo			MACH_VIVO		VIVO			2945
+bury_bl7582		MACH_BURY_BL7582	BURY_BL7582		2946
+bury_bps5270		MACH_BURY_BPS5270	BURY_BPS5270		2947
+basi			MACH_BASI		BASI			2948
+tn200			MACH_TN200		TN200			2949
+c2mmi			MACH_C2MMI		C2MMI			2950
+meson_6236m		MACH_MESON_6236M	MESON_6236M		2951
+meson_8626m		MACH_MESON_8626M	MESON_8626M		2952
+tube			MACH_TUBE		TUBE			2953
+messina			MACH_MESSINA		MESSINA			2954
+mx50_arm2		MACH_MX50_ARM2		MX50_ARM2		2955
+cetus9263		MACH_CETUS9263		CETUS9263		2956
 brownstone		MACH_BROWNSTONE		BROWNSTONE		2957
+vmx25			MACH_VMX25		VMX25			2958
+vmx51			MACH_VMX51		VMX51			2959
+abacus			MACH_ABACUS		ABACUS			2960
+cm4745			MACH_CM4745		CM4745			2961
+oratislink		MACH_ORATISLINK		ORATISLINK		2962
+davinci_dm365_dvr	MACH_DAVINCI_DM365_DVR	DAVINCI_DM365_DVR	2963
+netviz			MACH_NETVIZ		NETVIZ			2964
 flexibity		MACH_FLEXIBITY		FLEXIBITY		2965
+wlan_computer		MACH_WLAN_COMPUTER	WLAN_COMPUTER		2966
+lpc24xx			MACH_LPC24XX		LPC24XX			2967
+spica			MACH_SPICA		SPICA			2968
+gpsdisplay		MACH_GPSDISPLAY		GPSDISPLAY		2969
+bipnet			MACH_BIPNET		BIPNET			2970
+overo_ctu_inertial	MACH_OVERO_CTU_INERTIAL	OVERO_CTU_INERTIAL	2971
+davinci_dm355_mmm	MACH_DAVINCI_DM355_MMM	DAVINCI_DM355_MMM	2972
+pc9260_v2		MACH_PC9260_V2		PC9260_V2		2973
+ptx7545			MACH_PTX7545		PTX7545			2974
+tm_efdc			MACH_TM_EFDC		TM_EFDC			2975
+omap3_waldo1		MACH_OMAP3_WALDO1	OMAP3_WALDO1		2977
+flyer			MACH_FLYER		FLYER			2978
+tornado3240		MACH_TORNADO3240	TORNADO3240		2979
+soli_01			MACH_SOLI_01		SOLI_01			2980
+omapl138_europalc	MACH_OMAPL138_EUROPALC	OMAPL138_EUROPALC	2981
+helios_v1		MACH_HELIOS_V1		HELIOS_V1		2982
+netspace_lite_v2	MACH_NETSPACE_LITE_V2	NETSPACE_LITE_V2	2983
+ssc			MACH_SSC		SSC			2984
+premierwave_en		MACH_PREMIERWAVE_EN	PREMIERWAVE_EN		2985
+wasabi			MACH_WASABI		WASABI			2986
 mx50_rdp		MACH_MX50_RDP		MX50_RDP		2988
 universal_c210		MACH_UNIVERSAL_C210	UNIVERSAL_C210		2989
 real6410		MACH_REAL6410		REAL6410		2990
+spx_sakura		MACH_SPX_SAKURA		SPX_SAKURA		2991
+ij3k_2440		MACH_IJ3K_2440		IJ3K_2440		2992
+omap3_bc10		MACH_OMAP3_BC10		OMAP3_BC10		2993
+thebe			MACH_THEBE		THEBE			2994
+rv082			MACH_RV082		RV082			2995
+armlguest		MACH_ARMLGUEST		ARMLGUEST		2996
+tjinc1000		MACH_TJINC1000		TJINC1000		2997
 dockstar		MACH_DOCKSTAR		DOCKSTAR		2998
+ax8008			MACH_AX8008		AX8008			2999
+gnet_sgce		MACH_GNET_SGCE		GNET_SGCE		3000
+pxwnas_500_1000		MACH_PXWNAS_500_1000	PXWNAS_500_1000		3001
+ea20			MACH_EA20		EA20			3002
+awm2			MACH_AWM2		AWM2			3003
 ti8148evm		MACH_TI8148EVM		TI8148EVM		3004
 seaboard		MACH_SEABOARD		SEABOARD		3005
+linkstation_chlv2	MACH_LINKSTATION_CHLV2	LINKSTATION_CHLV2	3006
+tera_pro2_rack		MACH_TERA_PRO2_RACK	TERA_PRO2_RACK		3007
+rubys			MACH_RUBYS		RUBYS			3008
+aquarius		MACH_AQUARIUS		AQUARIUS		3009
 mx53_ard		MACH_MX53_ARD		MX53_ARD		3010
 mx53_smd		MACH_MX53_SMD		MX53_SMD		3011
+lswxl			MACH_LSWXL		LSWXL			3012
+dove_avng_v3		MACH_DOVE_AVNG_V3	DOVE_AVNG_V3		3013
+sdi_ess_9263		MACH_SDI_ESS_9263	SDI_ESS_9263		3014
+jocpu550		MACH_JOCPU550		JOCPU550		3015
 msm8x60_rumi3		MACH_MSM8X60_RUMI3	MSM8X60_RUMI3		3016
 msm8x60_ffa		MACH_MSM8X60_FFA	MSM8X60_FFA		3017
+yanomami		MACH_YANOMAMI		YANOMAMI		3018
+gta04			MACH_GTA04		GTA04			3019
 cm_a510			MACH_CM_A510		CM_A510			3020
+omap3_rfs200		MACH_OMAP3_RFS200	OMAP3_RFS200		3021
+kx33xx			MACH_KX33XX		KX33XX			3022
+ptx7510			MACH_PTX7510		PTX7510			3023
+top9000			MACH_TOP9000		TOP9000			3024
+teenote			MACH_TEENOTE		TEENOTE			3025
+ts3			MACH_TS3		TS3			3026
+a0			MACH_A0			A0			3027
+fsm9xxx_surf		MACH_FSM9XXX_SURF	FSM9XXX_SURF		3028
+fsm9xxx_ffa		MACH_FSM9XXX_FFA	FSM9XXX_FFA		3029
+frrhwcdma60w		MACH_FRRHWCDMA60W	FRRHWCDMA60W		3030
+remus			MACH_REMUS		REMUS			3031
+at91cap7xdk		MACH_AT91CAP7XDK	AT91CAP7XDK		3032
+at91cap7stk		MACH_AT91CAP7STK	AT91CAP7STK		3033
+kt_sbc_sam9_1		MACH_KT_SBC_SAM9_1	KT_SBC_SAM9_1		3034
+armada_xp_db		MACH_ARMADA_XP_DB	ARMADA_XP_DB		3036
+spdm			MACH_SPDM		SPDM			3037
+gtib			MACH_GTIB		GTIB			3038
+dgm3240			MACH_DGM3240		DGM3240			3039
+htcmega			MACH_HTCMEGA		HTCMEGA			3041
+tricorder		MACH_TRICORDER		TRICORDER		3042
 tx28			MACH_TX28		TX28			3043
+bstbrd			MACH_BSTBRD		BSTBRD			3044
+pwb3090			MACH_PWB3090		PWB3090			3045
+idea6410		MACH_IDEA6410		IDEA6410		3046
+qbc9263			MACH_QBC9263		QBC9263			3047
+borabora		MACH_BORABORA		BORABORA		3048
+valdez			MACH_VALDEZ		VALDEZ			3049
+ls9g20			MACH_LS9G20		LS9G20			3050
+mios_v1			MACH_MIOS_V1		MIOS_V1			3051
+s5pc110_crespo		MACH_S5PC110_CRESPO	S5PC110_CRESPO		3052
+controltek9g20		MACH_CONTROLTEK9G20	CONTROLTEK9G20		3053
+tin307			MACH_TIN307		TIN307			3054
+tin510			MACH_TIN510		TIN510			3055
+ep3505			MACH_EP3517		EP3517			3056
+bluecheese		MACH_BLUECHEESE		BLUECHEESE		3057
+tem3x30			MACH_TEM3X30		TEM3X30			3058
+harvest_desoto		MACH_HARVEST_DESOTO	HARVEST_DESOTO		3059
+msm8x60_qrdc		MACH_MSM8X60_QRDC	MSM8X60_QRDC		3060
+spear900		MACH_SPEAR900		SPEAR900		3061
 pcontrol_g20		MACH_PCONTROL_G20	PCONTROL_G20		3062
+rdstor			MACH_RDSTOR		RDSTOR			3063
+usdloader		MACH_USDLOADER		USDLOADER		3064
+tsoploader		MACH_TSOPLOADER		TSOPLOADER		3065
+kronos			MACH_KRONOS		KRONOS			3066
+ffcore			MACH_FFCORE		FFCORE			3067
+mone			MACH_MONE		MONE			3068
+unit2s			MACH_UNIT2S		UNIT2S			3069
+acer_a5			MACH_ACER_A5		ACER_A5			3070
+etherpro_isp		MACH_ETHERPRO_ISP	ETHERPRO_ISP		3071
+stretchs7000		MACH_STRETCHS7000	STRETCHS7000		3072
+p87_smartsim		MACH_P87_SMARTSIM	P87_SMARTSIM		3073
+tulip			MACH_TULIP		TULIP			3074
+sunflower		MACH_SUNFLOWER		SUNFLOWER		3075
+rib			MACH_RIB		RIB			3076
+clod			MACH_CLOD		CLOD			3077
+rump			MACH_RUMP		RUMP			3078
+tenderloin		MACH_TENDERLOIN		TENDERLOIN		3079
+shortloin		MACH_SHORTLOIN		SHORTLOIN		3080
+antares			MACH_ANTARES		ANTARES			3082
+wb40n			MACH_WB40N		WB40N			3083
+herring			MACH_HERRING		HERRING			3084
+naxy400			MACH_NAXY400		NAXY400			3085
+naxy1200		MACH_NAXY1200		NAXY1200		3086
 vpr200			MACH_VPR200		VPR200			3087
+bug20			MACH_BUG20		BUG20			3088
+goflexnet		MACH_GOFLEXNET		GOFLEXNET		3089
 torbreck		MACH_TORBRECK		TORBRECK		3090
+saarb_mg1		MACH_SAARB_MG1		SAARB_MG1		3091
+callisto		MACH_CALLISTO		CALLISTO		3092
+multhsu			MACH_MULTHSU		MULTHSU			3093
+saluda			MACH_SALUDA		SALUDA			3094
+pemp_omap3_apollo	MACH_PEMP_OMAP3_APOLLO	PEMP_OMAP3_APOLLO	3095
+vc0718			MACH_VC0718		VC0718			3096
+mvblx			MACH_MVBLX		MVBLX			3097
+inhand_apeiron		MACH_INHAND_APEIRON	INHAND_APEIRON		3098
+inhand_fury		MACH_INHAND_FURY	INHAND_FURY		3099
+inhand_siren		MACH_INHAND_SIREN	INHAND_SIREN		3100
+hdnvp			MACH_HDNVP		HDNVP			3101
+softwinner		MACH_SOFTWINNER		SOFTWINNER		3102
 prima2_evb		MACH_PRIMA2_EVB		PRIMA2_EVB		3103
+nas6210			MACH_NAS6210		NAS6210			3104
+unisdev			MACH_UNISDEV		UNISDEV			3105
+sbca11			MACH_SBCA11		SBCA11			3106
+saga			MACH_SAGA		SAGA			3107
+ns_k330			MACH_NS_K330		NS_K330			3108
+tanna			MACH_TANNA		TANNA			3109
+imate8502		MACH_IMATE8502		IMATE8502		3110
+aspen			MACH_ASPEN		ASPEN			3111
+daintree_cwac		MACH_DAINTREE_CWAC	DAINTREE_CWAC		3112
+zmx25			MACH_ZMX25		ZMX25			3113
+maple1			MACH_MAPLE1		MAPLE1			3114
+qsd8x72_surf		MACH_QSD8X72_SURF	QSD8X72_SURF		3115
+qsd8x72_ffa		MACH_QSD8X72_FFA	QSD8X72_FFA		3116
+abilene			MACH_ABILENE		ABILENE			3117
+eigen_ttr		MACH_EIGEN_TTR		EIGEN_TTR		3118
+iomega_ix2_200		MACH_IOMEGA_IX2_200	IOMEGA_IX2_200		3119
+coretec_vcx7400		MACH_CORETEC_VCX7400	CORETEC_VCX7400		3120
+santiago		MACH_SANTIAGO		SANTIAGO		3121
+mx257sol		MACH_MX257SOL		MX257SOL		3122
+strasbourg		MACH_STRASBOURG		STRASBOURG		3123
+msm8x60_fluid		MACH_MSM8X60_FLUID	MSM8X60_FLUID		3124
+smartqv5		MACH_SMARTQV5		SMARTQV5		3125
+smartqv3		MACH_SMARTQV3		SMARTQV3		3126
+smartqv7		MACH_SMARTQV7		SMARTQV7		3127
 paz00			MACH_PAZ00		PAZ00			3128
 acmenetusfoxg20		MACH_ACMENETUSFOXG20	ACMENETUSFOXG20		3129
+fwbd_0404		MACH_FWBD_0404		FWBD_0404		3131
+hdgu			MACH_HDGU		HDGU			3132
+pyramid			MACH_PYRAMID		PYRAMID			3133
+epiphan			MACH_EPIPHAN		EPIPHAN			3134
+omap_bender		MACH_OMAP_BENDER	OMAP_BENDER		3135
+gurnard			MACH_GURNARD		GURNARD			3136
+gtl_it5100		MACH_GTL_IT5100		GTL_IT5100		3137
+bcm2708			MACH_BCM2708		BCM2708			3138
+mx51_ggc		MACH_MX51_GGC		MX51_GGC		3139
+sharespace		MACH_SHARESPACE		SHARESPACE		3140
+haba_knx_explorer	MACH_HABA_KNX_EXPLORER	HABA_KNX_EXPLORER	3141
+simtec_kirkmod		MACH_SIMTEC_KIRKMOD	SIMTEC_KIRKMOD		3142
+crux			MACH_CRUX		CRUX			3143
+mx51_bravo		MACH_MX51_BRAVO		MX51_BRAVO		3144
+charon			MACH_CHARON		CHARON			3145
+picocom3		MACH_PICOCOM3		PICOCOM3		3146
+picocom4		MACH_PICOCOM4		PICOCOM4		3147
+serrano			MACH_SERRANO		SERRANO			3148
+doubleshot		MACH_DOUBLESHOT		DOUBLESHOT		3149
+evsy			MACH_EVSY		EVSY			3150
+huashan			MACH_HUASHAN		HUASHAN			3151
+lausanne		MACH_LAUSANNE		LAUSANNE		3152
+emerald			MACH_EMERALD		EMERALD			3153
+tqma35			MACH_TQMA35		TQMA35			3154
+marvel			MACH_MARVEL		MARVEL			3155
+manuae			MACH_MANUAE		MANUAE			3156
+chacha			MACH_CHACHA		CHACHA			3157
+lemon			MACH_LEMON		LEMON			3158
+csc			MACH_CSC		CSC			3159
+gira_knxip_router	MACH_GIRA_KNXIP_ROUTER	GIRA_KNXIP_ROUTER	3160
+t20			MACH_T20		T20			3161
+hdmini			MACH_HDMINI		HDMINI			3162
+sciphone_g2		MACH_SCIPHONE_G2	SCIPHONE_G2		3163
+express			MACH_EXPRESS		EXPRESS			3164
+express_kt		MACH_EXPRESS_KT		EXPRESS_KT		3165
+maximasp		MACH_MAXIMASP		MAXIMASP		3166
+nitrogen_imx51		MACH_NITROGEN_IMX51	NITROGEN_IMX51		3167
+nitrogen_imx53		MACH_NITROGEN_IMX53	NITROGEN_IMX53		3168
+sunfire			MACH_SUNFIRE		SUNFIRE			3169
+arowana			MACH_AROWANA		AROWANA			3170
+tegra_daytona		MACH_TEGRA_DAYTONA	TEGRA_DAYTONA		3171
+tegra_swordfish		MACH_TEGRA_SWORDFISH	TEGRA_SWORDFISH		3172
+edison			MACH_EDISON		EDISON			3173
+svp8500v1		MACH_SVP8500V1		SVP8500V1		3174
+svp8500v2		MACH_SVP8500V2		SVP8500V2		3175
+svp5500			MACH_SVP5500		SVP5500			3176
+b5500			MACH_B5500		B5500			3177
+s5500			MACH_S5500		S5500			3178
+icon			MACH_ICON		ICON			3179
+elephant		MACH_ELEPHANT		ELEPHANT		3180
+shooter			MACH_SHOOTER		SHOOTER			3182
+spade_lte		MACH_SPADE_LTE		SPADE_LTE		3183
+philhwani		MACH_PHILHWANI		PHILHWANI		3184
+gsncomm			MACH_GSNCOMM		GSNCOMM			3185
+strasbourg_a2		MACH_STRASBOURG_A2	STRASBOURG_A2		3186
+mmm			MACH_MMM		MMM			3187
+davinci_dm365_bv	MACH_DAVINCI_DM365_BV	DAVINCI_DM365_BV	3188
 ag5evm			MACH_AG5EVM		AG5EVM			3189
+sc575plc		MACH_SC575PLC		SC575PLC		3190
+sc575hmi		MACH_SC575IPC		SC575IPC		3191
+omap3_tdm3730		MACH_OMAP3_TDM3730	OMAP3_TDM3730		3192
+top9000_eval		MACH_TOP9000_EVAL	TOP9000_EVAL		3194
+top9000_su		MACH_TOP9000_SU		TOP9000_SU		3195
+utm300			MACH_UTM300		UTM300			3196
 tsunagi			MACH_TSUNAGI		TSUNAGI			3197
+ts75xx			MACH_TS75XX		TS75XX			3198
+ts47xx			MACH_TS47XX		TS47XX			3200
+da850_k5		MACH_DA850_K5		DA850_K5		3201
+ax502			MACH_AX502		AX502			3202
+igep0032		MACH_IGEP0032		IGEP0032		3203
+antero			MACH_ANTERO		ANTERO			3204
+synergy			MACH_SYNERGY		SYNERGY			3205
 ics_if_voip		MACH_ICS_IF_VOIP	ICS_IF_VOIP		3206
 wlf_cragg_6410		MACH_WLF_CRAGG_6410	WLF_CRAGG_6410		3207
+punica			MACH_PUNICA		PUNICA			3208
 trimslice		MACH_TRIMSLICE		TRIMSLICE		3209
+mx27_wmultra		MACH_MX27_WMULTRA	MX27_WMULTRA		3210
 mackerel		MACH_MACKEREL		MACKEREL		3211
+fa9x27			MACH_FA9X27		FA9X27			3213
+ns2816tb		MACH_NS2816TB		NS2816TB		3214
+ns2816_ntpad		MACH_NS2816_NTPAD	NS2816_NTPAD		3215
+ns2816_ntnb		MACH_NS2816_NTNB	NS2816_NTNB		3216
 kaen			MACH_KAEN		KAEN			3217
+nv1000			MACH_NV1000		NV1000			3218
+nuc950ts		MACH_NUC950TS		NUC950TS		3219
 nokia_rm680		MACH_NOKIA_RM680	NOKIA_RM680		3220
+ast2200			MACH_AST2200		AST2200			3221
+lead			MACH_LEAD		LEAD			3222
+unino1			MACH_UNINO1		UNINO1			3223
+greeco			MACH_GREECO		GREECO			3224
+verdi			MACH_VERDI		VERDI			3225
 dm6446_adbox		MACH_DM6446_ADBOX	DM6446_ADBOX		3226
 quad_salsa		MACH_QUAD_SALSA		QUAD_SALSA		3227
 abb_gma_1_1		MACH_ABB_GMA_1_1	ABB_GMA_1_1		3228
@@ -603,7 +3251,9 @@
 rascal			MACH_RASCAL		RASCAL			3292
 hrefv60			MACH_HREFV60		HREFV60			3293
 tpt_2_0			MACH_TPT_2_0		TPT_2_0			3294
+pydtd			MACH_PYRAMID_TD		PYRAMID_TD		3295
 splendor		MACH_SPLENDOR		SPLENDOR		3296
+guf_vincell		MACH_GUF_PLANET		GUF_PLANET		3297
 msm8x60_qt		MACH_MSM8X60_QT		MSM8X60_QT		3298
 htc_hd_mini		MACH_HTC_HD_MINI	HTC_HD_MINI		3299
 athene			MACH_ATHENE		ATHENE			3300
@@ -614,6 +3264,7 @@
 nmh			MACH_NMH		NMH			3305
 wn802t			MACH_WN802T		WN802T			3306
 dragonet		MACH_DRAGONET		DRAGONET		3307
+geneva_b4		MACH_GENEVA_B		GENEVA_B		3308
 at91sam9263desk16l	MACH_AT91SAM9263DESK16L	AT91SAM9263DESK16L	3309
 bcmhana_sv		MACH_BCMHANA_SV		BCMHANA_SV		3310
 bcmhana_tablet		MACH_BCMHANA_TABLET	BCMHANA_TABLET		3311
@@ -621,11 +3272,13 @@
 ts4800			MACH_TS4800		TS4800			3313
 tqma9263		MACH_TQMA9263		TQMA9263		3314
 holiday			MACH_HOLIDAY		HOLIDAY			3315
+dma_6410		MACH_DMA6410		DMA6410			3316
 pcats_overlay		MACH_PCATS_OVERLAY	PCATS_OVERLAY		3317
 hwgw6410		MACH_HWGW6410		HWGW6410		3318
 shenzhou		MACH_SHENZHOU		SHENZHOU		3319
 cwme9210		MACH_CWME9210		CWME9210		3320
 cwme9210js		MACH_CWME9210JS		CWME9210JS		3321
+pgs_v1			MACH_PGS_SITARA		PGS_SITARA		3322
 colibri_tegra2		MACH_COLIBRI_TEGRA2	COLIBRI_TEGRA2		3323
 w21			MACH_W21		W21			3324
 polysat1		MACH_POLYSAT1		POLYSAT1		3325
@@ -691,11 +3344,15 @@
 bockw			MACH_BOCKW		BOCKW			3386
 eva2000			MACH_EVA2000		EVA2000			3387
 steelyard		MACH_STEELYARD		STEELYARD		3388
+ea2468devkit		MACH_LPC2468OEM		LPC2468OEM		3389
+sdh001			MACH_MACH_SDH001	MACH_SDH001		3390
+fe2478mblox		MACH_LPC2478MICROBLOX	LPC2478MICROBLOX	3391
 nsslsboard		MACH_NSSLSBOARD		NSSLSBOARD		3392
 geneva_b5		MACH_GENEVA_B5		GENEVA_B5		3393
 spear1340		MACH_SPEAR1340		SPEAR1340		3394
 rexmas			MACH_REXMAS		REXMAS			3395
 msm8960_cdp		MACH_MSM8960_CDP	MSM8960_CDP		3396
+msm8960_mtp		MACH_MSM8960_MDP	MSM8960_MDP		3397
 msm8960_fluid		MACH_MSM8960_FLUID	MSM8960_FLUID		3398
 msm8960_apq		MACH_MSM8960_APQ	MSM8960_APQ		3399
 helios_v2		MACH_HELIOS_V2		HELIOS_V2		3400
@@ -727,6 +3384,7 @@
 ctera_plug_c2		MACH_CTERA_PLUG_C2	CTERA_PLUG_C2		3426
 marvelct		MACH_MARVELCT		MARVELCT		3427
 ag11005			MACH_AG11005		AG11005			3428
+omap_tabletblaze	MACH_OMAP_BLAZE		OMAP_BLAZE		3429
 vangogh			MACH_VANGOGH		VANGOGH			3430
 matrix505		MACH_MATRIX505		MATRIX505		3431
 oce_nigma		MACH_OCE_NIGMA		OCE_NIGMA		3432
@@ -766,6 +3424,7 @@
 mini210			MACH_MINI210		MINI210			3466
 mini8168		MACH_MINI8168		MINI8168		3467
 pc7308			MACH_PC7308		PC7308			3468
+ge863_pro3_evk		MACH_GE863		GE863			3469
 kmm2m01			MACH_KMM2M01		KMM2M01			3470
 mx51erebus		MACH_MX51EREBUS		MX51EREBUS		3471
 wm8650refboard		MACH_WM8650REFBOARD	WM8650REFBOARD		3472
@@ -802,6 +3461,7 @@
 nspire			MACH_NSPIRE		NSPIRE			3503
 mickxx			MACH_MICKXX		MICKXX			3504
 lxmb			MACH_LXMB		LXMB			3505
+tmdxscbp6618x		MACH_TMDXSCBP6616X	TMDXSCBP6616X		3506
 adam			MACH_ADAM		ADAM			3507
 b1004			MACH_B1004		B1004			3508
 oboea			MACH_OBOEA		OBOEA			3509
@@ -879,6 +3539,7 @@
 tuscan			MACH_TUSCAN		TUSCAN			3583
 xbt_sam9g45		MACH_XBT_SAM9G45	XBT_SAM9G45		3584
 enbw_cmc		MACH_ENBW_CMC		ENBW_CMC		3585
+msm8x60_dragon		MACH_APQ8060_DRAGON	APQ8060_DRAGON		3586
 ch104mx257		MACH_CH104MX257		CH104MX257		3587
 openpri			MACH_OPENPRI		OPENPRI			3588
 am335xevm		MACH_AM335XEVM		AM335XEVM		3589
@@ -900,6 +3561,7 @@
 cinema_tea		MACH_CINEMA_TEA		CINEMA_TEA		3605
 cinema_coffee		MACH_CINEMA_COFFEE	CINEMA_COFFEE		3606
 cinema_juice		MACH_CINEMA_JUICE	CINEMA_JUICE		3607
+linux_pad		MACH_THEPAD		THEPAD			3608
 mx53_mirage2		MACH_MX53_MIRAGE2	MX53_MIRAGE2		3609
 mx53_efikasb		MACH_MX53_EFIKASB	MX53_EFIKASB		3610
 stm_b2000		MACH_STM_B2000		STM_B2000		3612
@@ -965,6 +3627,7 @@
 cedar			MACH_CEDAR		CEDAR			3672
 picasso_e		MACH_PICASSO_E		PICASSO_E		3673
 samsung_e60		MACH_SAMSUNG_E60	SAMSUNG_E60		3674
+msm9615_cdp		MACH_MDM9615		MDM9615			3675
 sdvr_mini		MACH_SDVR_MINI		SDVR_MINI		3676
 omap3_ij3k		MACH_OMAP3_IJ3K		OMAP3_IJ3K		3677
 modasmc1		MACH_MODASMC1		MODASMC1		3678
@@ -992,6 +3655,8 @@
 fmc_dcm			MACH_FMC_DCM		FMC_DCM			3700
 batwm			MACH_BATWM		BATWM			3701
 atlas6cb		MACH_ATLAS6CB		ATLAS6CB		3702
+quattro_f		MACH_QUATTROF		QUATTROF		3703
+quattro_u		MACH_QUATTROU		QUATTROU		3704
 blue			MACH_BLUE		BLUE			3705
 colorado		MACH_COLORADO		COLORADO		3706
 popc			MACH_POPC		POPC			3707
@@ -999,15 +3664,19 @@
 amp			MACH_AMP		AMP			3709
 gnet_amp		MACH_GNET_AMP		GNET_AMP		3710
 toques			MACH_TOQUES		TOQUES			3711
+apx4devkit		MACH_APX4DEVKIT		APX4DEVKIT		3712
 dct_storm		MACH_DCT_STORM		DCT_STORM		3713
+dm8168z3		MACH_Z3			Z3			3714
 owl			MACH_OWL		OWL			3715
 cogent_csb1741		MACH_COGENT_CSB1741	COGENT_CSB1741		3716
+omap3_kiko		MACH_OMAP3		OMAP3			3717
 adillustra610		MACH_ADILLUSTRA610	ADILLUSTRA610		3718
 ecafe_na04		MACH_ECAFE_NA04		ECAFE_NA04		3719
 popct			MACH_POPCT		POPCT			3720
 omap3_helena		MACH_OMAP3_HELENA	OMAP3_HELENA		3721
 ach			MACH_ACH		ACH			3722
 module_dtb		MACH_MODULE_DTB		MODULE_DTB		3723
+ratebox			MACH_RACKBOX		RACKBOX			3724
 oslo_elisabeth		MACH_OSLO_ELISABETH	OSLO_ELISABETH		3725
 tt01			MACH_TT01		TT01			3726
 msm8930_cdp		MACH_MSM8930_CDP	MSM8930_CDP		3727
@@ -1038,6 +3707,7 @@
 ptip_classic		MACH_PTIP_CLASSIC	PTIP_CLASSIC		3753
 mx53grb			MACH_MX53GRB		MX53GRB			3754
 gagarin			MACH_GAGARIN		GAGARIN			3755
+msm7627a_qrd1		MACH_MSM7X27A_QRD1	MSM7X27A_QRD1		3756
 nas2big			MACH_NAS2BIG		NAS2BIG			3757
 superfemto		MACH_SUPERFEMTO		SUPERFEMTO		3758
 teufel			MACH_TEUFEL		TEUFEL			3759
@@ -1087,6 +3757,7 @@
 mx53_pf1		MACH_MX53_PF1		MX53_PF1		3803
 asanti			MACH_ASANTI		ASANTI			3804
 volta			MACH_VOLTA		VOLTA			3805
+potenza			MACH_S5P6450		S5P6450			3806
 knight			MACH_KNIGHT		KNIGHT			3807
 beaglebone		MACH_BEAGLEBONE		BEAGLEBONE		3808
 becker			MACH_BECKER		BECKER			3809
@@ -1148,6 +3819,7 @@
 primoc			MACH_PRIMOC		PRIMOC			3865
 primoct			MACH_PRIMOCT		PRIMOCT			3866
 a9500			MACH_A9500		A9500			3867
+pue_td			MACH_PULSE_TD		PULSE_TD		3868
 pluto			MACH_PLUTO		PLUTO			3869
 acfx100			MACH_ACFX100		ACFX100			3870
 msm8625_rumi3		MACH_MSM8625_RUMI3	MSM8625_RUMI3		3871
@@ -1161,6 +3833,8 @@
 huangshans		MACH_HUANGSHANS		HUANGSHANS		3879
 bosphorus1		MACH_BOSPHORUS1		BOSPHORUS1		3880
 prima			MACH_PRIMA		PRIMA			3881
+meson3_skt		MACH_M3_SKT		M3_SKT			3882
+meson3_ref		MACH_M3_REF		M3_REF			3883
 evita_ulk		MACH_EVITA_ULK		EVITA_ULK		3884
 merisc600		MACH_MERISC600		MERISC600		3885
 dolak			MACH_DOLAK		DOLAK			3886
@@ -1169,3 +3843,271 @@
 pov2			MACH_POV2		POV2			3889
 ipod_touch_2g		MACH_IPOD_TOUCH_2G	IPOD_TOUCH_2G		3890
 da850_pqab		MACH_DA850_PQAB		DA850_PQAB		3891
+fermi			MACH_FERMI		FERMI			3892
+ccardwmx28		MACH_CCARDWMX28		CCARDWMX28		3893
+ccardmx28		MACH_CCARDMX28		CCARDMX28		3894
+fs20_fcm2050		MACH_FS20_FCM2050	FS20_FCM2050		3895
+kinetis			MACH_KINETIS		KINETIS			3896
+kai			MACH_KAI		KAI			3897
+bcthb2			MACH_BCTHB2		BCTHB2			3898
+inels3_cu		MACH_INELS3_CU		INELS3_CU		3899
+da850_juniper		MACH_JUNIPER		JUNIPER			3900
+da850_apollo		MACH_DA850_APOLLO	DA850_APOLLO		3901
+tracnas			MACH_TRACNAS		TRACNAS			3902
+mityarm335x		MACH_MITYARM335X	MITYARM335X		3903
+xcgz7x			MACH_XCGZ7X		XCGZ7X			3904
+cubox			MACH_CUBOX		CUBOX			3905
+terminator		MACH_TERMINATOR		TERMINATOR		3906
+eye03			MACH_EYE03		EYE03			3907
+kota3			MACH_KOTA3		KOTA3			3908
+mx53_nitrogen_k		MACH_MX5		MX5			3909
+pscpe			MACH_PSCPE		PSCPE			3910
+akt1100			MACH_AKT1100		AKT1100			3911
+pcaaxl2			MACH_PCAAXL2		PCAAXL2			3912
+primodd_ct		MACH_PRIMODD_CT		PRIMODD_CT		3913
+nsbc			MACH_NSBC		NSBC			3914
+meson2_skt		MACH_MESON2_SKT		MESON2_SKT		3915
+meson2_ref		MACH_MESON2_REF		MESON2_REF		3916
+ccardwmx28js		MACH_CCARDWMX28JS	CCARDWMX28JS		3917
+ccardmx28js		MACH_CCARDMX28JS	CCARDMX28JS		3918
+indico			MACH_INDICO		INDICO			3919
+msm8960dt		MACH_MSM8960DT		MSM8960DT		3920
+primods			MACH_PRIMODS		PRIMODS			3921
+beluga_m1388		MACH_BELUGA_M1388	BELUGA_M1388		3922
+primotd			MACH_PRIMOTD		PRIMOTD			3923
+varan_master		MACH_VARAN_MASTER	VARAN_MASTER		3924
+primodd			MACH_PRIMODD		PRIMODD			3925
+jetduo			MACH_JETDUO		JETDUO			3926
+mx53_umobo		MACH_MX53_UMOBO		MX53_UMOBO		3927
+trats			MACH_TRATS		TRATS			3928
+starcraft		MACH_STARCRAFT		STARCRAFT		3929
+qseven_tegra2		MACH_QSEVEN_TEGRA2	QSEVEN_TEGRA2		3930
+lichee_sun4i_devbd	MACH_LICHEE_SUN4I_DEVBD	LICHEE_SUN4I_DEVBD	3931
+movenow			MACH_MOVENOW		MOVENOW			3932
+golf_u			MACH_GOLF_U		GOLF_U			3933
+msm7627a_evb		MACH_MSM7627A_EVB	MSM7627A_EVB		3934
+rambo			MACH_RAMBO		RAMBO			3935
+golfu			MACH_GOLFU		GOLFU			3936
+mango310		MACH_MANGO310		MANGO310		3937
+dns343			MACH_DNS343		DNS343			3938
+var_som_om44		MACH_VAR_SOM_OM44	VAR_SOM_OM44		3939
+naon			MACH_NAON		NAON			3940
+vp4000			MACH_VP4000		VP4000			3941
+impcard			MACH_IMPCARD		IMPCARD			3942
+smoovcam		MACH_SMOOVCAM		SMOOVCAM		3943
+cobham3725		MACH_COBHAM3725		COBHAM3725		3944
+cobham3730		MACH_COBHAM3730		COBHAM3730		3945
+cobham3703		MACH_COBHAM3703		COBHAM3703		3946
+quetzal			MACH_QUETZAL		QUETZAL			3947
+apq8064_cdp		MACH_APQ8064_CDP	APQ8064_CDP		3948
+apq8064_mtp		MACH_APQ8064_MTP	APQ8064_MTP		3949
+apq8064_fluid		MACH_APQ8064_FLUID	APQ8064_FLUID		3950
+apq8064_liquid		MACH_APQ8064_LIQUID	APQ8064_LIQUID		3951
+mango210		MACH_MANGO210		MANGO210		3952
+mango100		MACH_MANGO100		MANGO100		3953
+mango24			MACH_MANGO24		MANGO24			3954
+mango64			MACH_MANGO64		MANGO64			3955
+nsa320			MACH_NSA320		NSA320			3956
+elv_ccu2		MACH_ELV_CCU2		ELV_CCU2		3957
+triton_x00		MACH_TRITON_X00		TRITON_X00		3958
+triton_1500_2000	MACH_TRITON_1500_2000	TRITON_1500_2000	3959
+pogoplugv4		MACH_POGOPLUGV4		POGOPLUGV4		3960
+venus_cl		MACH_VENUS_CL		VENUS_CL		3961
+vulcano_g20		MACH_VULCANO_G20	VULCANO_G20		3962
+sgs_i9100		MACH_SGS_I9100		SGS_I9100		3963
+stsv2			MACH_STSV2		STSV2			3964
+csb1724			MACH_CSB1724		CSB1724			3965
+omapl138_lcdk		MACH_OMAPL138_LCDK	OMAPL138_LCDK		3966
+jel_dd			MACH_JEWEL_DD		JEWEL_DD		3967
+pvd_mx25		MACH_PVD_MX25		PVD_MX25		3968
+meson6_skt		MACH_MESON6_SKT		MESON6_SKT		3969
+meson6_ref		MACH_MESON6_REF		MESON6_REF		3970
+pxm			MACH_PXM		PXM			3971
+stuttgart		MACH_S3			S3			3972
+pogoplugv3		MACH_POGOPLUGV3		POGOPLUGV3		3973
+mlp89626		MACH_MLP89626		MLP89626		3974
+iomegahmndce		MACH_IOMEGAHMNDCE	IOMEGAHMNDCE		3975
+pogoplugv3pci		MACH_POGOPLUGV3PCI	POGOPLUGV3PCI		3976
+bntv250			MACH_BNTV250		BNTV250			3977
+mx53_qseven		MACH_MX53_QSEVEN	MX53_QSEVEN		3978
+gtl_it1100		MACH_GTL_IT1100		GTL_IT1100		3979
+mx6q_sabresd		MACH_MX6Q_SABRESD	MX6Q_SABRESD		3980
+mt4			MACH_MT4		MT4			3981
+jumbo_d			MACH_JUMBO_D		JUMBO_D			3982
+jumbo_i			MACH_JUMBO_I		JUMBO_I			3983
+fs20_dmp		MACH_FS20_DMP		FS20_DMP		3984
+dns320			MACH_DNS320		DNS320			3985
+mx28bacos		MACH_MX28BACOS		MX28BACOS		3986
+tl80			MACH_TL80		TL80			3987
+polatis_nic_1001	MACH_POLATIS_NIC_1001	POLATIS_NIC_1001	3988
+tely			MACH_TELY		TELY			3989
+u8520			MACH_U8520		U8520			3990
+manta			MACH_MANTA		MANTA			3991
+spear1340_lcad		MACH_SPEAR_EM_S900	SPEAR_EM_S900		3992
+mpq8064_cdp		MACH_MPQ8064_CDP	MPQ8064_CDP		3993
+mpq8064_hrd		MACH_MPQ8064_STB	MPQ8064_STB		3994
+mpq8064_dtv		MACH_MPQ8064_DTV	MPQ8064_DTV		3995
+dm368som		MACH_DM368SOM		DM368SOM		3996
+gprisb2			MACH_GPRISB2		GPRISB2			3997
+chammid			MACH_CHAMMID		CHAMMID			3998
+seoul2			MACH_SEOUL2		SEOUL2			3999
+omap4_nooktablet	MACH_OMAP4_NOOKTABLET	OMAP4_NOOKTABLET	4000
+aalto			MACH_AALTO		AALTO			4001
+metro			MACH_METRO		METRO			4002
+cydm3730		MACH_CYDM3730		CYDM3730		4003
+tqma53			MACH_TQMA53		TQMA53			4004
+msm7627a_qrd3		MACH_MSM7627A_QRD3	MSM7627A_QRD3		4005
+mx28_canby		MACH_MX28_CANBY		MX28_CANBY		4006
+tiger			MACH_TIGER		TIGER			4007
+pcats_9307_type_a	MACH_PCATS_9307_TYPE_A	PCATS_9307_TYPE_A	4008
+pcats_9307_type_o	MACH_PCATS_9307_TYPE_O	PCATS_9307_TYPE_O	4009
+pcats_9307_type_r	MACH_PCATS_9307_TYPE_R	PCATS_9307_TYPE_R	4010
+streamplug		MACH_STREAMPLUG		STREAMPLUG		4011
+icechicken_dev		MACH_ICECHICKEN_DEV	ICECHICKEN_DEV		4012
+hedgehog		MACH_HEDGEHOG		HEDGEHOG		4013
+yusend_obc		MACH_YUSEND_OBC		YUSEND_OBC		4014
+imxninja		MACH_IMXNINJA		IMXNINJA		4015
+omap4_jarod		MACH_OMAP4_JAROD	OMAP4_JAROD		4016
+eco5_pk			MACH_ECO5_PK		ECO5_PK			4017
+qj2440			MACH_QJ2440		QJ2440			4018
+mx6q_mercury		MACH_MX6Q_MERCURY	MX6Q_MERCURY		4019
+cm6810			MACH_CM6810		CM6810			4020
+omap4_torpedo		MACH_OMAP4_TORPEDO	OMAP4_TORPEDO		4021
+nsa310			MACH_NSA310		NSA310			4022
+tmx536			MACH_TMX536		TMX536			4023
+ktt20			MACH_KTT20		KTT20			4024
+dragonix		MACH_DRAGONIX		DRAGONIX		4025
+lungching		MACH_LUNGCHING		LUNGCHING		4026
+bulogics		MACH_BULOGICS		BULOGICS		4027
+mx535_sx		MACH_MX535_SX		MX535_SX		4028
+ngui3250		MACH_NGUI3250		NGUI3250		4029
+salutec_dac		MACH_SALUTEC_DAC	SALUTEC_DAC		4030
+loco			MACH_LOCO		LOCO			4031
+ctera_plug_usi		MACH_CTERA_PLUG_USI	CTERA_PLUG_USI		4032
+scepter			MACH_SCEPTER		SCEPTER			4033
+sga			MACH_SGA		SGA			4034
+p_81_j5			MACH_P_81_J5		P_81_J5			4035
+p_81_o4			MACH_P_81_O4		P_81_O4			4036
+msm8625_surf		MACH_MSM8625_SURF	MSM8625_SURF		4037
+carallon_shark		MACH_CARALLON_SHARK	CARALLON_SHARK		4038
+lsgc_icam		MACH_LSGCICAM		LSGCICAM		4039
+ordog			MACH_ORDOG		ORDOG			4040
+puente_io		MACH_PUENTE_IO		PUENTE_IO		4041
+msm8625_evb		MACH_MSM8625_EVB	MSM8625_EVB		4042
+ev_am1707		MACH_EV_AM1707		EV_AM1707		4043
+ev_am1707e2		MACH_EV_AM1707E2	EV_AM1707E2		4044
+ev_am3517e2		MACH_EV_AM3517E2	EV_AM3517E2		4045
+calabria		MACH_CALABRIA		CALABRIA		4046
+ev_imx287		MACH_EV_IMX287		EV_IMX287		4047
+erau			MACH_ERAU		ERAU			4048
+sichuan			MACH_SICHUAN		SICHUAN			4049
+sopdm			MACH_WIRMA3		WIRMA3			4050
+davinci_da850		MACH_DAVINCI_DA850	DAVINCI_DA850		4051
+omap138_trunarc		MACH_OMAP138_TRUNARC	OMAP138_TRUNARC		4052
+bcm4761			MACH_BCM4761		BCM4761			4053
+picasso_e2		MACH_PICASSO_E2		PICASSO_E2		4054
+picasso_mf		MACH_PICASSO_MF		PICASSO_MF		4055
+miro			MACH_MIRO		MIRO			4056
+at91sam9g20ewon3	MACH_AT91SAM9G20EWON3	AT91SAM9G20EWON3	4057
+yoyo			MACH_YOYO		YOYO			4058
+windjkl			MACH_WINDJKL		WINDJKL			4059
+monarudo		MACH_MONARUDO		MONARUDO		4060
+batan			MACH_BATAN		BATAN			4061
+tadao			MACH_TADAO		TADAO			4062
+baso			MACH_BASO		BASO			4063
+mahon			MACH_MAHON		MAHON			4064
+villec2			MACH_VILLEC2		VILLEC2			4065
+asi1230			MACH_ASI1230		ASI1230			4066
+alaska			MACH_ALASKA		ALASKA			4067
+swarco_shdsl2		MACH_SWARCO_SHDSL2	SWARCO_SHDSL2		4068
+oxrtu			MACH_OXRTU		OXRTU			4069
+omap5_panda		MACH_OMAP5_PANDA	OMAP5_PANDA		4070
+imx286			MACH_MX28XDI		MX28XDI			4071
+c8000			MACH_C8000		C8000			4072
+bje_display3_5		MACH_BJE_DISPLAY3_5	BJE_DISPLAY3_5		4073
+picomod7		MACH_PICOMOD7		PICOMOD7		4074
+picocom5		MACH_PICOCOM5		PICOCOM5		4075
+qblissa8		MACH_QBLISSA8		QBLISSA8		4076
+armstonea8		MACH_ARMSTONEA8		ARMSTONEA8		4077
+netdcu14		MACH_NETDCU14		NETDCU14		4078
+at91sam9x5_epiphan	MACH_AT91SAM9X5_EPIPHAN	AT91SAM9X5_EPIPHAN	4079
+p2u			MACH_P2U		P2U			4080
+doris			MACH_DORIS		DORIS			4081
+j49			MACH_J49		J49			4082
+vdss2e			MACH_VDSS2E		VDSS2E			4083
+vc300			MACH_VC300		VC300			4084
+ns115_pad_test		MACH_NS115_PAD_TEST	NS115_PAD_TEST		4085
+ns115_pad_ref		MACH_NS115_PAD_REF	NS115_PAD_REF		4086
+ns115_phone_test	MACH_NS115_PHONE_TEST	NS115_PHONE_TEST	4087
+ns115_phone_ref		MACH_NS115_PHONE_REF	NS115_PHONE_REF		4088
+golfc			MACH_GOLFC		GOLFC			4089
+xerox_olympus		MACH_XEROX_OLYMPUS	XEROX_OLYMPUS		4090
+mx6sl_arm2		MACH_MX6SL_ARM2		MX6SL_ARM2		4091
+csb1701_csb1726		MACH_CSB1701_CSB1726	CSB1701_CSB1726		4092
+at91sam9xeek		MACH_AT91SAM9XEEK	AT91SAM9XEEK		4093
+ebv210			MACH_EBV210		EBV210			4094
+msm7627a_qrd7		MACH_MSM7627A_QRD7	MSM7627A_QRD7		4095
+svthin			MACH_SVTHIN		SVTHIN			4096
+duovero			MACH_DUOVERO		DUOVERO			4097
+chupacabra		MACH_CHUPACABRA		CHUPACABRA		4098
+scorpion		MACH_SCORPION		SCORPION		4099
+davinci_he_hmi10	MACH_DAVINCI_HE_HMI10	DAVINCI_HE_HMI10	4100
+topkick			MACH_TOPKICK		TOPKICK			4101
+m3_auguestrush		MACH_M3_AUGUESTRUSH	M3_AUGUESTRUSH		4102
+ipc335x			MACH_IPC335X		IPC335X			4103
+sun4i			MACH_SUN4I		SUN4I			4104
+imx233_olinuxino	MACH_IMX233_OLINUXINO	IMX233_OLINUXINO	4105
+k2_wl			MACH_K2_WL		K2_WL			4106
+k2_ul			MACH_K2_UL		K2_UL			4107
+k2_cl			MACH_K2_CL		K2_CL			4108
+minbari_w		MACH_MINBARI_W		MINBARI_W		4109
+minbari_m		MACH_MINBARI_M		MINBARI_M		4110
+k035			MACH_K035		K035			4111
+ariel			MACH_ARIEL		ARIEL			4112
+arielsaarc		MACH_ARIELSAARC		ARIELSAARC		4113
+arieldkb		MACH_ARIELDKB		ARIELDKB		4114
+armadillo810		MACH_ARMADILLO810	ARMADILLO810		4115
+tam335x			MACH_TAM335X		TAM335X			4116
+grouper			MACH_GROUPER		GROUPER			4117
+mpcsa21_9g20		MACH_MPCSA21_9G20	MPCSA21_9G20		4118
+m6u_cpu			MACH_M6U_CPU		M6U_CPU			4119
+davinci_dp10		MACH_DAVINCI_DP10	DAVINCI_DP10		4120
+ginkgo			MACH_GINKGO		GINKGO			4121
+cgt_qmx6		MACH_CGT_QMX6		CGT_QMX6		4122
+profpga			MACH_PROFPGA		PROFPGA			4123
+acfx100oc		MACH_ACFX100OC		ACFX100OC		4124
+acfx100nb		MACH_ACFX100NB		ACFX100NB		4125
+capricorn		MACH_CAPRICORN		CAPRICORN		4126
+pisces			MACH_PISCES		PISCES			4127
+aries			MACH_ARIES		ARIES			4128
+cancer			MACH_CANCER		CANCER			4129
+leo			MACH_LEO		LEO			4130
+virgo			MACH_VIRGO		VIRGO			4131
+sagittarius		MACH_SAGITTARIUS	SAGITTARIUS		4132
+devil			MACH_DEVIL		DEVIL			4133
+ballantines		MACH_BALLANTINES	BALLANTINES		4134
+omap3_procerusvpu	MACH_OMAP3_PROCERUSVPU	OMAP3_PROCERUSVPU	4135
+my27			MACH_MY27		MY27			4136
+sun6i			MACH_SUN6I		SUN6I			4137
+sun5i			MACH_SUN5I		SUN5I			4138
+mx512_mx		MACH_MX512_MX		MX512_MX		4139
+kzm9g			MACH_KZM9G		KZM9G			4140
+vdstbn			MACH_VDSTBN		VDSTBN			4141
+cfa10036		MACH_CFA10036		CFA10036		4142
+cfa10049		MACH_CFA10049		CFA10049		4143
+pcm051			MACH_PCM051		PCM051			4144
+vybrid_vf7xx		MACH_VYBRID_VF7XX	VYBRID_VF7XX		4145
+vybrid_vf6xx		MACH_VYBRID_VF6XX	VYBRID_VF6XX		4146
+vybrid_vf5xx		MACH_VYBRID_VF5XX	VYBRID_VF5XX		4147
+vybrid_vf4xx		MACH_VYBRID_VF4XX	VYBRID_VF4XX		4148
+aria_g25		MACH_ARIA_G25		ARIA_G25		4149
+bcm21553		MACH_BCM21553		BCM21553		4150
+smdk5410		MACH_SMDK5410		SMDK5410		4151
+lpc18xx			MACH_LPC18XX		LPC18XX			4152
+oratisparty		MACH_ORATISPARTY	ORATISPARTY		4153
+qseven			MACH_QSEVEN		QSEVEN			4154
+gmv_generic		MACH_GMV_GENERIC	GMV_GENERIC		4155
+th_link_eth		MACH_TH_LINK_ETH	TH_LINK_ETH		4156
+tn_muninn		MACH_TN_MUNINN		TN_MUNINN		4157
+rampage			MACH_RAMPAGE		RAMPAGE			4158
+visstrim_mv10		MACH_VISSTRIM_MV10	VISSTRIM_MV10		4159
diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c
index 782c3a35..3540c5e 100644
--- a/arch/ia64/kernel/irq_ia64.c
+++ b/arch/ia64/kernel/irq_ia64.c
@@ -23,7 +23,6 @@
 #include <linux/ioport.h>
 #include <linux/kernel_stat.h>
 #include <linux/ptrace.h>
-#include <linux/random.h>	/* for rand_initialize_irq() */
 #include <linux/signal.h>
 #include <linux/smp.h>
 #include <linux/threads.h>
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 5ab6e89..cffcae6 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -877,9 +877,6 @@
 config ARCH_MAY_HAVE_PC_FDC
 	bool
 
-config BOOT_RAW
-	bool
-
 config CEVT_BCM1480
 	bool
 
@@ -964,6 +961,17 @@
 config MIPS_BONITO64
 	bool
 
+config MIPS_FPU_EMU
+	bool "Enable FPU emulation"
+	default y
+	help
+	   This option allows building a kernel with or without the Algorithmics
+	   FPU emulator enabled. Turning off this option results in a kernel which
+	   does not catch floating operations exceptions. Make sure that your toolchain
+	   is configured to enable software floating point emulation in that case.
+		
+	   If unsure say Y here.
+
 config MIPS_MSC
 	bool
 
@@ -979,6 +987,10 @@
 config MIPS_MACHINE
 	def_bool n
 
+config IMAGE_CMDLINE_HACK
+	bool "OpenWrt specific image command line hack"
+	default n
+
 config NO_IOPORT
 	def_bool n
 
@@ -2330,6 +2342,18 @@
 	help
 	  Include support for flattened device tree machine descriptions.
 
+config BOOT_RAW
+	bool "Enable the kernel to be executed from the load address"
+	default n
+	help
+	 Allow the kernel to be executed from the load address for
+	 bootloaders which cannot read the ELF format. This places
+	 a jump to start_kernel at the load address.
+
+	 If unsure, say N.
+
+
+
 endmenu
 
 config LOCKDEP_SUPPORT
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 4fedf5a..a5a427b 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -90,8 +90,8 @@
 cflags-y			+= -G 0 -mno-abicalls -fno-pic -pipe
 cflags-y			+= -msoft-float
 LDFLAGS_vmlinux			+= -G 0 -static -n -nostdlib
-KBUILD_AFLAGS_MODULE		+= -mlong-calls
-KBUILD_CFLAGS_MODULE		+= -mlong-calls
+KBUILD_AFLAGS_MODULE		+= -mno-long-calls
+KBUILD_CFLAGS_MODULE		+= -mno-long-calls
 
 cflags-y += -ffreestanding
 
diff --git a/arch/mips/include/asm/asm_nosec.h b/arch/mips/include/asm/asm_nosec.h
new file mode 100644
index 0000000..ae5cd40
--- /dev/null
+++ b/arch/mips/include/asm/asm_nosec.h
@@ -0,0 +1,53 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995, 1996, 1997, 1999, 2001 by Ralf Baechle
+ * Copyright (C) 1999 by Silicon Graphics, Inc.
+ * Copyright (C) 2001 MIPS Technologies, Inc.
+ * Copyright (C) 2002  Maciej W. Rozycki
+ * Copyright (C) 2010  Wu Zhangjin <wuzhangjin@gmail.com>
+ *
+ * Derive from <asm/asm.h>
+ *
+ * Override the macros without -ffunction-sections and -fdata-sections support.
+ * If several functions or data must be put in the same section, please include
+ * this header file after the <asm/asm.h> to override the generic definition.
+ */
+
+#ifndef __ASM_ASM_NOSEC_H
+#define __ASM_ASM_NOSEC_H
+
+#undef LEAF
+#undef NESTED
+#undef EXPORT
+
+/*
+ * LEAF - declare leaf routine
+ */
+#define	LEAF(symbol)                                    \
+		.globl	symbol;                         \
+		.align	2;                              \
+		.type	symbol, @function;              \
+		.ent	symbol, 0;                      \
+symbol:		.frame	sp, 0, ra
+
+/*
+ * NESTED - declare nested routine entry point
+ */
+#define	NESTED(symbol, framesize, rpc)                  \
+		.globl	symbol;                         \
+		.align	2;                              \
+		.type	symbol, @function;              \
+		.ent	symbol, 0;                       \
+symbol:		.frame	sp, framesize, rpc
+
+/*
+ * EXPORT - export definition of symbol
+ */
+#define EXPORT(symbol)					\
+		.globl	symbol;                         \
+symbol:
+
+#endif /* __ASM_ASM_NOSEC_H */
diff --git a/arch/mips/include/asm/kexec.h b/arch/mips/include/asm/kexec.h
index 4314892..fe63d28 100644
--- a/arch/mips/include/asm/kexec.h
+++ b/arch/mips/include/asm/kexec.h
@@ -9,22 +9,55 @@
 #ifndef _MIPS_KEXEC
 # define _MIPS_KEXEC
 
+#include <asm/stacktrace.h>
+
+extern unsigned long long elfcorehdr_addr;
+
 /* Maximum physical address we can use pages from */
 #define KEXEC_SOURCE_MEMORY_LIMIT (0x20000000)
 /* Maximum address we can reach in physical address mode */
 #define KEXEC_DESTINATION_MEMORY_LIMIT (0x20000000)
  /* Maximum address we can use for the control code buffer */
 #define KEXEC_CONTROL_MEMORY_LIMIT (0x20000000)
-
-#define KEXEC_CONTROL_PAGE_SIZE 4096
+/* Reserve 3*4096 bytes for board-specific info */
+#define KEXEC_CONTROL_PAGE_SIZE (4096 + 3*4096)
 
 /* The native architecture */
 #define KEXEC_ARCH KEXEC_ARCH_MIPS
+#define MAX_NOTE_BYTES 1024
 
 static inline void crash_setup_regs(struct pt_regs *newregs,
-				    struct pt_regs *oldregs)
+					struct pt_regs *oldregs)
 {
-	/* Dummy implementation for now */
+	if (oldregs)
+		memcpy(newregs, oldregs, sizeof(*newregs));
+	else
+		prepare_frametrace(newregs);
 }
 
+#ifdef CONFIG_KEXEC
+
+#define __kexec __attribute__((__section__(".__kexec.relocate")))
+
+/* The linker tells us where the relocate_new_kernel part is. */
+extern const unsigned char __start___kexec_relocate;
+extern const unsigned char __end___kexec_relocate;
+
+extern unsigned long kexec_start_address;
+extern unsigned long kexec_indirection_page;
+
+struct kimage;
+extern unsigned long kexec_args[4];
+extern int (*_machine_kexec_prepare)(struct kimage *);
+extern void (*_machine_kexec_shutdown)(void);
+extern void (*_machine_crash_shutdown)(struct pt_regs *regs);
+extern void default_machine_crash_shutdown(struct pt_regs *regs);
+#ifdef CONFIG_SMP
+extern const unsigned char kexec_smp_wait[];
+extern unsigned long secondary_kexec_args[4];
+extern void (*relocated_kexec_smp_wait) (void *);
+extern atomic_t kexec_ready_to_reboot;
+#endif
+#endif
+
 #endif /* !_MIPS_KEXEC */
diff --git a/arch/mips/include/asm/module.h b/arch/mips/include/asm/module.h
index 7467d1d..5ed6a8f 100644
--- a/arch/mips/include/asm/module.h
+++ b/arch/mips/include/asm/module.h
@@ -9,6 +9,11 @@
 	struct list_head dbe_list;
 	const struct exception_table_entry *dbe_start;
 	const struct exception_table_entry *dbe_end;
+
+	void *phys_plt_tbl;
+	void *virt_plt_tbl;
+	unsigned int phys_plt_offset;
+	unsigned int virt_plt_offset;
 };
 
 typedef uint8_t Elf64_Byte;		/* Type for a 8-bit quantity.  */
diff --git a/arch/mips/include/asm/smp.h b/arch/mips/include/asm/smp.h
index d4fb4d8..f1578f9 100644
--- a/arch/mips/include/asm/smp.h
+++ b/arch/mips/include/asm/smp.h
@@ -40,6 +40,8 @@
 #define SMP_CALL_FUNCTION	0x2
 /* Octeon - Tell another core to flush its icache */
 #define SMP_ICACHE_FLUSH	0x4
+/* Used by kexec crashdump to save all cpu's state */
+#define SMP_DUMP		0x8
 
 extern volatile cpumask_t cpu_callin_map;
 
@@ -91,4 +93,9 @@
 	mp_ops->send_ipi_mask(mask, SMP_CALL_FUNCTION);
 }
 
+extern void core_send_ipi(int cpu, unsigned int action);
+#if defined(CONFIG_KEXEC)
+extern void (*dump_ipi_function_ptr)(void *);
+void dump_send_ipi(void (*dump_ipi_callback)(void *));
+#endif
 #endif /* __ASM_SMP_H */
diff --git a/arch/mips/include/asm/string.h b/arch/mips/include/asm/string.h
index 436e3ad..5a66ec4 100644
--- a/arch/mips/include/asm/string.h
+++ b/arch/mips/include/asm/string.h
@@ -133,11 +133,44 @@
 
 #define __HAVE_ARCH_MEMSET
 extern void *memset(void *__s, int __c, size_t __count);
+#define memset(__s, __c, len)					\
+({								\
+	size_t __len = (len);					\
+	void *__ret;						\
+	if (__builtin_constant_p(len) && __len >= 64)		\
+		__ret = memset((__s), (__c), __len);		\
+	else							\
+		__ret = __builtin_memset((__s), (__c), __len);	\
+	__ret;							\
+})
 
 #define __HAVE_ARCH_MEMCPY
 extern void *memcpy(void *__to, __const__ void *__from, size_t __n);
+#define memcpy(dst, src, len)					\
+({								\
+	size_t __len = (len);					\
+	void *__ret;						\
+	if (__builtin_constant_p(len) && __len >= 64)		\
+		__ret = memcpy((dst), (src), __len);		\
+	else							\
+		__ret = __builtin_memcpy((dst), (src), __len);	\
+	__ret;							\
+})
 
 #define __HAVE_ARCH_MEMMOVE
 extern void *memmove(void *__dest, __const__ void *__src, size_t __n);
+#define memmove(dst, src, len)					\
+({								\
+	size_t __len = (len);					\
+	void *__ret;						\
+	if (__builtin_constant_p(len) && __len >= 64)		\
+		__ret = memmove((dst), (src), __len);		\
+	else							\
+		__ret = __builtin_memmove((dst), (src), __len);	\
+	__ret;							\
+})
+
+#define __HAVE_ARCH_MEMCMP
+#define memcmp(src1, src2, len) __builtin_memcmp((src1), (src2), (len))
 
 #endif /* _ASM_STRING_H */
diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h
index 0d85d8e..6b74308 100644
--- a/arch/mips/include/asm/thread_info.h
+++ b/arch/mips/include/asm/thread_info.h
@@ -85,6 +85,7 @@
 
 #define STACK_WARN	(THREAD_SIZE / 8)
 
+#if 0
 #define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
 
 #ifdef CONFIG_DEBUG_STACK_USAGE
@@ -96,6 +97,7 @@
 #endif
 
 #define free_thread_info(info) kfree(info)
+#endif
 
 #endif /* !__ASSEMBLY__ */
 
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 0c6877e..cacc340 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -97,7 +97,8 @@
 
 obj-$(CONFIG_GPIO_TXX9)		+= gpio_txx9.o
 
-obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel.o
+obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel.o crash.o
+obj-$(CONFIG_CRASH_DUMP)	+= crash_dump.o
 obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
 obj-$(CONFIG_SPINLOCK_TEST)	+= spinlock_test.o
 obj-$(CONFIG_MIPS_MACHINE)	+= mips_machine.o
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 0bab464..d69747b 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -816,10 +816,13 @@
 		__cpu_name[cpu] = "MIPS 20Kc";
 		break;
 	case PRID_IMP_24K:
-	case PRID_IMP_24KE:
 		c->cputype = CPU_24K;
 		__cpu_name[cpu] = "MIPS 24Kc";
 		break;
+	case PRID_IMP_24KE:
+		c->cputype = CPU_24K;
+		__cpu_name[cpu] = "MIPS 24KEc";
+		break;
 	case PRID_IMP_25KF:
 		c->cputype = CPU_25KF;
 		__cpu_name[cpu] = "MIPS 25Kc";
diff --git a/arch/mips/kernel/crash.c b/arch/mips/kernel/crash.c
new file mode 100644
index 0000000..9a2ca49
--- /dev/null
+++ b/arch/mips/kernel/crash.c
@@ -0,0 +1,75 @@
+#include <linux/kernel.h>
+#include <linux/smp.h>
+#include <linux/reboot.h>
+#include <linux/kexec.h>
+#include <linux/bootmem.h>
+#include <linux/crash_dump.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+
+#ifdef CONFIG_CRASH_DUMP
+unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX;
+#endif
+
+/* This keeps a track of which one is crashing cpu. */
+int crashing_cpu = -1;
+static cpumask_t cpus_in_crash = CPU_MASK_NONE;
+
+#ifdef CONFIG_SMP
+void crash_shutdown_secondary(void *ignore)
+{
+	struct pt_regs *regs;
+	int cpu = smp_processor_id();
+
+	regs = task_pt_regs(current);
+
+	if (!cpu_online(cpu))
+		return;
+
+	local_irq_disable();
+	if (!cpu_isset(cpu, cpus_in_crash))
+		crash_save_cpu(regs, cpu);
+	cpu_set(cpu, cpus_in_crash);
+
+	while (!atomic_read(&kexec_ready_to_reboot))
+		cpu_relax();
+	relocated_kexec_smp_wait(NULL);
+	/* NOTREACHED */
+}
+
+static void crash_kexec_prepare_cpus(void)
+{
+	unsigned int msecs;
+
+	unsigned int ncpus = num_online_cpus() - 1;/* Excluding the panic cpu */
+
+	dump_send_ipi(crash_shutdown_secondary);
+	smp_wmb();
+
+	/*
+	 * The crash CPU sends an IPI and wait for other CPUs to
+	 * respond. Delay of at least 10 seconds.
+	 */
+	printk(KERN_EMERG "Sending IPI to other cpus...\n");
+	msecs = 10000;
+	while ((cpus_weight(cpus_in_crash) < ncpus) && (--msecs > 0)) {
+		cpu_relax();
+		mdelay(1);
+	}
+}
+
+#else
+static void crash_kexec_prepare_cpus(void) {}
+#endif
+
+void default_machine_crash_shutdown(struct pt_regs *regs)
+{
+	local_irq_disable();
+	crashing_cpu = smp_processor_id();
+	crash_save_cpu(regs, crashing_cpu);
+	crash_kexec_prepare_cpus();
+	cpu_set(crashing_cpu, cpus_in_crash);
+}
diff --git a/arch/mips/kernel/crash_dump.c b/arch/mips/kernel/crash_dump.c
new file mode 100644
index 0000000..540853d
--- /dev/null
+++ b/arch/mips/kernel/crash_dump.c
@@ -0,0 +1,86 @@
+#include <linux/highmem.h>
+#include <linux/bootmem.h>
+#include <linux/crash_dump.h>
+#include <asm/uaccess.h>
+
+#ifdef CONFIG_PROC_VMCORE
+static int __init parse_elfcorehdr(char *p)
+{
+	if (p)
+		elfcorehdr_addr = memparse(p, &p);
+	return 1;
+}
+__setup("elfcorehdr=", parse_elfcorehdr);
+#endif
+
+static int __init parse_savemaxmem(char *p)
+{
+	if (p)
+		saved_max_pfn = (memparse(p, &p) >> PAGE_SHIFT) - 1;
+
+	return 1;
+}
+__setup("savemaxmem=", parse_savemaxmem);
+
+
+static void *kdump_buf_page;
+
+/**
+ * copy_oldmem_page - copy one page from "oldmem"
+ * @pfn: page frame number to be copied
+ * @buf: target memory address for the copy; this can be in kernel address
+ *	space or user address space (see @userbuf)
+ * @csize: number of bytes to copy
+ * @offset: offset in bytes into the page (based on pfn) to begin the copy
+ * @userbuf: if set, @buf is in user address space, use copy_to_user(),
+ *	otherwise @buf is in kernel address space, use memcpy().
+ *
+ * Copy a page from "oldmem". For this page, there is no pte mapped
+ * in the current kernel.
+ *
+ * Calling copy_to_user() in atomic context is not desirable. Hence first
+ * copying the data to a pre-allocated kernel page and then copying to user
+ * space in non-atomic context.
+ */
+ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
+		size_t csize, unsigned long offset, int userbuf)
+{
+	void  *vaddr;
+
+	if (!csize)
+		return 0;
+
+	vaddr = kmap_atomic_pfn(pfn, KM_PTE0);
+
+	if (!userbuf) {
+		memcpy(buf, (vaddr + offset), csize);
+		kunmap_atomic(vaddr, KM_PTE0);
+	} else {
+		if (!kdump_buf_page) {
+			printk(KERN_WARNING "Kdump: Kdump buffer page not"
+				" allocated\n");
+			return -EFAULT;
+		}
+		copy_page(kdump_buf_page, vaddr);
+		kunmap_atomic(vaddr, KM_PTE0);
+		if (copy_to_user(buf, (kdump_buf_page + offset), csize))
+			return -EFAULT;
+	}
+
+	return csize;
+}
+
+static int __init kdump_buf_page_init(void)
+{
+	int ret = 0;
+
+	kdump_buf_page = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!kdump_buf_page) {
+		printk(KERN_WARNING "Kdump: Failed to allocate kdump buffer"
+			 " page\n");
+		ret = -ENOMEM;
+	}
+
+	return ret;
+}
+arch_initcall(kdump_buf_page_init);
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
index ea695d9..5bb5240 100644
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -141,6 +141,12 @@
 	j	kernel_entry
 #endif
 
+#ifdef CONFIG_IMAGE_CMDLINE_HACK
+	.ascii	"CMDLINE:"
+EXPORT(__image_cmdline)
+	.fill	0x400
+#endif /* CONFIG_IMAGE_CMDLINE_HACK */
+
 	__REF
 
 NESTED(kernel_entry, 16, sp)			# kernel entry point
diff --git a/arch/mips/kernel/machine_kexec.c b/arch/mips/kernel/machine_kexec.c
index 85beb9b..9114109 100644
--- a/arch/mips/kernel/machine_kexec.c
+++ b/arch/mips/kernel/machine_kexec.c
@@ -10,18 +10,139 @@
 #include <linux/mm.h>
 #include <linux/delay.h>
 
+#include <asm/bootinfo.h>
 #include <asm/cacheflush.h>
 #include <asm/page.h>
+#include <asm/uaccess.h>
 
-extern const unsigned char relocate_new_kernel[];
-extern const size_t relocate_new_kernel_size;
+int (*_machine_kexec_prepare)(struct kimage *) = NULL;
+void (*_machine_kexec_shutdown)(void) = NULL;
+void (*_machine_crash_shutdown)(struct pt_regs *regs) = NULL;
+#ifdef CONFIG_SMP
+void (*relocated_kexec_smp_wait) (void *);
+atomic_t kexec_ready_to_reboot = ATOMIC_INIT(0);
+#endif
 
-extern unsigned long kexec_start_address;
-extern unsigned long kexec_indirection_page;
+#define KEXEC_MIPS_ARGV_BUF_SIZE	COMMAND_LINE_SIZE
+#define KEXEC_MIPS_ARGV_MAX_ARGS	(COMMAND_LINE_SIZE / 15)
+
+char kexec_argv_buf[KEXEC_MIPS_ARGV_BUF_SIZE] __kexec;
+char *kexec_argv[KEXEC_MIPS_ARGV_MAX_ARGS] __kexec;
+
+static void
+machine_kexec_print_args(void)
+{
+	int i;
+
+	pr_info("kexec_args[0] (argc): %lu\n", kexec_args[0]);
+	pr_info("kexec_args[1] (argv): %p\n", (void *)kexec_args[1]);
+	pr_info("kexec_args[2] (env ): %p\n", (void *)kexec_args[2]);
+	pr_info("kexec_args[3] (desc): %p\n", (void *)kexec_args[3]);
+
+	for (i = 0; i < kexec_args[0]; i++)
+		pr_info("kexec_argv[%d] = %p, %s\n", i,
+			(char *)kexec_argv[i], (char *)kexec_argv[i]);
+}
+
+static void
+machine_kexec_init_argv(struct kimage *image)
+{
+	void __user *buf = NULL;
+	size_t bufsz;
+	size_t size;
+	int i;
+
+	bufsz = 0;
+	for (i = 0; i < image->nr_segments; i++) {
+		struct kexec_segment *seg;
+
+		seg = &image->segment[i];
+		if (seg->bufsz < 6)
+			continue;
+
+		if (strncmp((char *) seg->buf, "kexec", 5))
+			continue;
+
+		/* don't copy "kexec" */
+		buf = seg->buf + 5;
+		bufsz = seg->bufsz - 5;
+		break;
+	}
+
+	if (!buf)
+		return;
+
+	size = KEXEC_MIPS_ARGV_BUF_SIZE - 1;
+	size = min(size, bufsz);
+	if (size < bufsz)
+		pr_warn("kexec command line truncated to %zd bytes\n", size);
+
+	/* Copy to kernel space */
+	copy_from_user(kexec_argv_buf, buf, size);
+}
+
+static void
+machine_kexec_parse_argv(struct kimage *image)
+{
+	char *reboot_code_buffer;
+	int reloc_delta;
+	char *ptr;
+	int argc;
+	int i;
+
+	ptr = kexec_argv_buf;
+	argc = 0;
+
+	/*
+	 * convert command line string to array of parameters
+	 * (as bootloader does).
+	 */
+	while (ptr && *ptr && (KEXEC_MIPS_ARGV_MAX_ARGS > argc)) {
+		if (*ptr == ' ') {
+			*ptr++ = '\0';
+			continue;
+		}
+
+		kexec_argv[argc++] = ptr;
+		ptr = strchr(ptr, ' ');
+	}
+
+	if (!argc)
+		return;
+
+	kexec_args[0] = argc;
+	kexec_args[1] = (unsigned long)kexec_argv;
+	kexec_args[2] = 0;
+	kexec_args[3] = 0;
+
+	reboot_code_buffer = page_address(image->control_code_page);
+	reloc_delta = reboot_code_buffer - (char *) &__start___kexec_relocate;
+
+	kexec_args[1] += reloc_delta;
+	for (i = 0; i < argc; i++)
+		kexec_argv[i] += reloc_delta;
+}
 
 int
 machine_kexec_prepare(struct kimage *kimage)
 {
+	/*
+	 * Whenever arguments passed from kexec-tools, Init the arguments as
+	 * the original ones to avoid booting failure.
+	 *
+	 * This can be overrided by _machine_kexec_prepare().
+	 */
+
+	kexec_args[0] = fw_arg0;
+	kexec_args[1] = fw_arg1;
+	kexec_args[2] = fw_arg2;
+	kexec_args[3] = fw_arg3;
+
+	machine_kexec_init_argv(kimage);
+	machine_kexec_parse_argv(kimage);
+
+	if (_machine_kexec_prepare)
+		return _machine_kexec_prepare(kimage);
 	return 0;
 }
 
@@ -33,11 +154,17 @@
 void
 machine_shutdown(void)
 {
+	if (_machine_kexec_shutdown)
+		_machine_kexec_shutdown();
 }
 
 void
 machine_crash_shutdown(struct pt_regs *regs)
 {
+	if (_machine_crash_shutdown)
+		_machine_crash_shutdown(regs);
+	else
+		default_machine_crash_shutdown(regs);
 }
 
 typedef void (*noretfun_t)(void) __attribute__((noreturn));
@@ -45,25 +172,42 @@
 void
 machine_kexec(struct kimage *image)
 {
+	unsigned long kexec_relocate_size;
 	unsigned long reboot_code_buffer;
 	unsigned long entry;
 	unsigned long *ptr;
 
+	kexec_relocate_size = (unsigned long)(&__end___kexec_relocate) -
+		(unsigned long)(&__start___kexec_relocate);
+	pr_info("kexec_relocate_size = %lu\n", kexec_relocate_size);
+
 	reboot_code_buffer =
 	  (unsigned long)page_address(image->control_code_page);
+	pr_info("reboot_code_buffer = %p\n", (void *)reboot_code_buffer);
 
-	kexec_start_address = image->start;
+	kexec_start_address =
+	  (unsigned long) phys_to_virt(image->start);
+	pr_info("kexec_start_address(entry point of new kernel) = %p\n",
+			(void *)kexec_start_address);
+
 	kexec_indirection_page =
 		(unsigned long) phys_to_virt(image->head & PAGE_MASK);
+	pr_info("kexec_indirection_page = %p\n",
+			(void *)kexec_indirection_page);
 
-	memcpy((void*)reboot_code_buffer, relocate_new_kernel,
-	       relocate_new_kernel_size);
+	pr_info("Copy kexec_relocate section from %p to reboot_code_buffer: %p\n",
+			&__start___kexec_relocate, (void *)reboot_code_buffer);
+
+	memcpy((void *)reboot_code_buffer, &__start___kexec_relocate,
+	       kexec_relocate_size);
+
+	machine_kexec_print_args();
 
 	/*
 	 * The generic kexec code builds a page list with physical
 	 * addresses. they are directly accessible through KSEG0 (or
 	 * CKSEG0 or XPHYS if on 64bit system), hence the
-	 * pys_to_virt() call.
+	 * phys_to_virt() call.
 	 */
 	for (ptr = &image->head; (entry = *ptr) && !(entry &IND_DONE);
 	     ptr = (entry & IND_INDIRECTION) ?
@@ -78,8 +222,15 @@
 	 */
 	local_irq_disable();
 
-	printk("Will call new kernel at %08lx\n", image->start);
-	printk("Bye ...\n");
+	pr_info("Will call new kernel at %p\n", (void *)kexec_start_address);
+	pr_info("Bye ...\n");
 	__flush_cache_all();
+#ifdef CONFIG_SMP
+	/* All secondary cpus now may jump to kexec_wait cycle */
+	relocated_kexec_smp_wait = reboot_code_buffer +
+		(void *)(kexec_smp_wait - relocate_new_kernel);
+	smp_wmb();
+	atomic_set(&kexec_ready_to_reboot, 1);
+#endif
 	((noretfun_t) reboot_code_buffer)();
 }
diff --git a/arch/mips/kernel/module.c b/arch/mips/kernel/module.c
index a5066b1..e3b69cc 100644
--- a/arch/mips/kernel/module.c
+++ b/arch/mips/kernel/module.c
@@ -44,14 +44,219 @@
 static LIST_HEAD(dbe_list);
 static DEFINE_SPINLOCK(dbe_lock);
 
-#ifdef MODULE_START
+/*
+ * Get the potential max trampolines size required of the init and
+ * non-init sections. Only used if we cannot find enough contiguous
+ * physically mapped memory to put the module into.
+ */
+static unsigned int
+get_plt_size(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
+             const char *secstrings, unsigned int symindex, bool is_init)
+{
+	unsigned long ret = 0;
+	unsigned int i, j;
+	Elf_Sym *syms;
+
+	/* Everything marked ALLOC (this includes the exported symbols) */
+	for (i = 1; i < hdr->e_shnum; ++i) {
+		unsigned int info = sechdrs[i].sh_info;
+
+		if (sechdrs[i].sh_type != SHT_REL
+		    && sechdrs[i].sh_type != SHT_RELA)
+			continue;
+
+		/* Not a valid relocation section? */
+		if (info >= hdr->e_shnum)
+			continue;
+
+		/* Don't bother with non-allocated sections */
+		if (!(sechdrs[info].sh_flags & SHF_ALLOC))
+			continue;
+
+		/* If it's called *.init*, and we're not init, we're
+                   not interested */
+		if ((strstr(secstrings + sechdrs[i].sh_name, ".init") != 0)
+		    != is_init)
+			continue;
+
+		syms = (Elf_Sym *) sechdrs[symindex].sh_addr;
+		if (sechdrs[i].sh_type == SHT_REL) {
+			Elf_Mips_Rel *rel = (void *) sechdrs[i].sh_addr;
+			unsigned int size = sechdrs[i].sh_size / sizeof(*rel);
+
+			for (j = 0; j < size; ++j) {
+				Elf_Sym *sym;
+
+				if (ELF_MIPS_R_TYPE(rel[j]) != R_MIPS_26)
+					continue;
+
+				sym = syms + ELF_MIPS_R_SYM(rel[j]);
+				if (!is_init && sym->st_shndx != SHN_UNDEF)
+					continue;
+
+				ret += 4 * sizeof(int);
+			}
+		} else {
+			Elf_Mips_Rela *rela = (void *) sechdrs[i].sh_addr;
+			unsigned int size = sechdrs[i].sh_size / sizeof(*rela);
+
+			for (j = 0; j < size; ++j) {
+				Elf_Sym *sym;
+
+				if (ELF_MIPS_R_TYPE(rela[j]) != R_MIPS_26)
+					continue;
+
+				sym = syms + ELF_MIPS_R_SYM(rela[j]);
+				if (!is_init && sym->st_shndx != SHN_UNDEF)
+					continue;
+
+				ret += 4 * sizeof(int);
+			}
+		}
+	}
+
+	return ret;
+}
+
+#ifndef MODULE_START
+static void *alloc_phys(unsigned long size)
+{
+	unsigned order;
+	struct page *page;
+	struct page *p;
+
+	size = PAGE_ALIGN(size);
+	order = get_order(size);
+
+	page = alloc_pages(GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN |
+			__GFP_THISNODE, order);
+	if (!page)
+		return NULL;
+
+	split_page(page, order);
+
+	for (p = page + (size >> PAGE_SHIFT); p < page + (1 << order); ++p)
+		__free_page(p);
+
+	return page_address(page);
+}
+#endif
+
+static void free_phys(void *ptr, unsigned long size)
+{
+	struct page *page;
+	struct page *end;
+
+	page = virt_to_page(ptr);
+	end = page + (PAGE_ALIGN(size) >> PAGE_SHIFT);
+
+	for (; page < end; ++page)
+		__free_page(page);
+}
+
+
 void *module_alloc(unsigned long size)
 {
+#ifdef MODULE_START
 	return __vmalloc_node_range(size, 1, MODULE_START, MODULE_END,
 				GFP_KERNEL, PAGE_KERNEL, -1,
 				__builtin_return_address(0));
-}
+#else
+	void *ptr;
+
+	if (size == 0)
+		return NULL;
+
+	ptr = alloc_phys(size);
+
+	/* If we failed to allocate physically contiguous memory,
+	 * fall back to regular vmalloc. The module loader code will
+	 * create jump tables to handle long jumps */
+	if (!ptr)
+		return vmalloc(size);
+
+	return ptr;
 #endif
+}
+
+static inline bool is_phys_addr(void *ptr)
+{
+#ifdef CONFIG_64BIT
+	return (KSEGX((unsigned long)ptr) == CKSEG0);
+#else
+	return (KSEGX(ptr) == KSEG0);
+#endif
+}
+
+/* Free memory returned from module_alloc */
+void module_free(struct module *mod, void *module_region)
+{
+	if (is_phys_addr(module_region)) {
+		if (mod->module_init == module_region)
+			free_phys(module_region, mod->init_size);
+		else if (mod->module_core == module_region)
+			free_phys(module_region, mod->core_size);
+		else
+			BUG();
+	} else {
+		vfree(module_region);
+	}
+}
+
+static void *__module_alloc(int size, bool phys)
+{
+	void *ptr;
+
+	if (phys)
+		ptr = kmalloc(size, GFP_KERNEL);
+	else
+		ptr = vmalloc(size);
+	return ptr;
+}
+
+static void __module_free(void *ptr)
+{
+	if (is_phys_addr(ptr))
+		kfree(ptr);
+	else
+		vfree(ptr);
+}
+
+int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
+			      char *secstrings, struct module *mod)
+{
+	unsigned int symindex = 0;
+	unsigned int core_size, init_size;
+	int i;
+
+	for (i = 1; i < hdr->e_shnum; i++)
+		if (sechdrs[i].sh_type == SHT_SYMTAB)
+			symindex = i;
+
+	core_size = get_plt_size(hdr, sechdrs, secstrings, symindex, false);
+	init_size = get_plt_size(hdr, sechdrs, secstrings, symindex, true);
+
+	mod->arch.phys_plt_offset = 0;
+	mod->arch.virt_plt_offset = 0;
+	mod->arch.phys_plt_tbl = NULL;
+	mod->arch.virt_plt_tbl = NULL;
+
+	if ((core_size + init_size) == 0)
+		return 0;
+
+	mod->arch.phys_plt_tbl = __module_alloc(core_size + init_size, 1);
+	if (!mod->arch.phys_plt_tbl)
+		return -ENOMEM;
+
+	mod->arch.virt_plt_tbl = __module_alloc(core_size + init_size, 0);
+	if (!mod->arch.virt_plt_tbl) {
+		__module_free(mod->arch.phys_plt_tbl);
+		mod->arch.phys_plt_tbl = NULL;
+		return -ENOMEM;
+	}
+
+	return 0;
+}
 
 static int apply_r_mips_none(struct module *me, u32 *location, Elf_Addr v)
 {
@@ -72,28 +277,36 @@
 	return 0;
 }
 
-static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v)
+static Elf_Addr add_plt_entry_to(unsigned *plt_offset,
+				 void *start, Elf_Addr v)
 {
-	if (v % 4) {
-		pr_err("module %s: dangerous R_MIPS_26 REL relocation\n",
-		       me->name);
-		return -ENOEXEC;
-	}
+	unsigned *tramp = start + *plt_offset;
+	*plt_offset += 4 * sizeof(int);
 
-	if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) {
-		printk(KERN_ERR
-		       "module %s: relocation overflow\n",
-		       me->name);
-		return -ENOEXEC;
-	}
+	/* adjust carry for addiu */
+	if (v & 0x00008000)
+		v += 0x10000;
 
-	*location = (*location & ~0x03ffffff) |
-	            ((*location + (v >> 2)) & 0x03ffffff);
+	tramp[0] = 0x3c190000 | (v >> 16);      /* lui t9, hi16 */
+	tramp[1] = 0x27390000 | (v & 0xffff);   /* addiu t9, t9, lo16 */
+	tramp[2] = 0x03200008;                  /* jr t9 */
+	tramp[3] = 0x00000000;                  /* nop */
 
-	return 0;
+	return (Elf_Addr) tramp;
 }
 
-static int apply_r_mips_26_rela(struct module *me, u32 *location, Elf_Addr v)
+static Elf_Addr add_plt_entry(struct module *me, void *location, Elf_Addr v)
+{
+	if (is_phys_addr(location))
+		return add_plt_entry_to(&me->arch.phys_plt_offset,
+				me->arch.phys_plt_tbl, v);
+	else
+		return add_plt_entry_to(&me->arch.virt_plt_offset,
+				me->arch.virt_plt_tbl, v);
+
+}
+
+static int set_r_mips_26(struct module *me, u32 *location, u32 ofs, Elf_Addr v)
 {
 	if (v % 4) {
 		pr_err("module %s: dangerous R_MIPS_26 RELArelocation\n",
@@ -102,17 +315,31 @@
 	}
 
 	if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) {
-		printk(KERN_ERR
+	    v = add_plt_entry(me, location, v + (ofs << 2));
+		if (!v) {
+			printk(KERN_ERR
 		       "module %s: relocation overflow\n",
 		       me->name);
-		return -ENOEXEC;
+			return -ENOEXEC;
+		}
+		ofs = 0;
 	}
 
-	*location = (*location & ~0x03ffffff) | ((v >> 2) & 0x03ffffff);
+	*location = (*location & ~0x03ffffff) | ((ofs + (v >> 2)) & 0x03ffffff);
 
 	return 0;
 }
 
+static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v)
+{
+	return set_r_mips_26(me, location, *location & 0x03ffffff, v);
+}
+
+static int apply_r_mips_26_rela(struct module *me, u32 *location, Elf_Addr v)
+{
+	return set_r_mips_26(me, location, 0, v);
+}
+
 static int apply_r_mips_hi16_rel(struct module *me, u32 *location, Elf_Addr v)
 {
 	struct mips_hi16 *n;
@@ -380,11 +607,32 @@
 		list_add(&me->arch.dbe_list, &dbe_list);
 		spin_unlock_irq(&dbe_lock);
 	}
+
+	/* Get rid of the fixup trampoline if we're running the module
+	 * from physically mapped address space */
+	if (me->arch.phys_plt_offset == 0) {
+		__module_free(me->arch.phys_plt_tbl);
+		me->arch.phys_plt_tbl = NULL;
+	}
+	if (me->arch.virt_plt_offset == 0) {
+		__module_free(me->arch.virt_plt_tbl);
+		me->arch.virt_plt_tbl = NULL;
+	}
+
 	return 0;
 }
 
 void module_arch_cleanup(struct module *mod)
 {
+	if (mod->arch.phys_plt_tbl) {
+		__module_free(mod->arch.phys_plt_tbl);
+		mod->arch.phys_plt_tbl = NULL;
+	}
+	if (mod->arch.virt_plt_tbl) {
+		__module_free(mod->arch.virt_plt_tbl);
+		mod->arch.virt_plt_tbl = NULL;
+	}
+
 	spin_lock_irq(&dbe_lock);
 	list_del(&mod->arch.dbe_list);
 	spin_unlock_irq(&dbe_lock);
diff --git a/arch/mips/kernel/relocate_kernel.S b/arch/mips/kernel/relocate_kernel.S
index 87481f9..ac79106 100644
--- a/arch/mips/kernel/relocate_kernel.S
+++ b/arch/mips/kernel/relocate_kernel.S
@@ -7,6 +7,7 @@
  */
 
 #include <asm/asm.h>
+#include <asm/asm_nosec.h>
 #include <asm/asmmacro.h>
 #include <asm/regdef.h>
 #include <asm/page.h>
@@ -14,7 +15,14 @@
 #include <asm/stackframe.h>
 #include <asm/addrspace.h>
 
+	.section	.kexec.relocate, "ax"
+
 LEAF(relocate_new_kernel)
+	PTR_L a0,	arg0
+	PTR_L a1,	arg1
+	PTR_L a2,	arg2
+	PTR_L a3,	arg3
+
 	PTR_L		s0, kexec_indirection_page
 	PTR_L		s1, kexec_start_address
 
@@ -26,7 +34,6 @@
 	and		s3, s2, 0x1
 	beq		s3, zero, 1f
 	and		s4, s2, ~0x1	/* store destination addr in s4 */
-	move		a0, s4
 	b		process_entry
 
 1:
@@ -60,23 +67,94 @@
 	b		process_entry
 
 done:
+#ifdef CONFIG_SMP
+	/* kexec_flag reset is signal to other CPUs what kernel
+ 	   was moved to it's location. Note - we need relocated address
+ 	   of kexec_flag.  */
+
+ 	bal		1f
+ 1: 	move		t1,ra;
+ 	PTR_LA		t2,1b
+ 	PTR_LA		t0,kexec_flag
+ 	PTR_SUB		t0,t0,t2;
+ 	PTR_ADD		t0,t1,t0;
+ 	LONG_S		zero,(t0)
+#endif
+
+	sync
 	/* jump to kexec_start_address */
 	j		s1
 	END(relocate_new_kernel)
 
-kexec_start_address:
-	EXPORT(kexec_start_address)
+#ifdef CONFIG_SMP
+/*
+ * Other CPUs should wait until code is relocated and
+ * then start at entry (?) point.
+ */
+LEAF(kexec_smp_wait)
+	PTR_L		a0, s_arg0
+	PTR_L		a1, s_arg1
+	PTR_L		a2, s_arg2
+	PTR_L		a3, s_arg3
+	PTR_L		s1, kexec_start_address
+
+	/* Non-relocated address works for args and kexec_start_address ( old
+	 * kernel is not overwritten). But we need relocated address of
+	 * kexec_flag.
+	 */
+
+	bal		1f
+1:	move		t1,ra;
+	PTR_LA		t2,1b
+	PTR_LA		t0,kexec_flag
+	PTR_SUB		t0,t0,t2;
+	PTR_ADD		t0,t1,t0;
+
+1:	LONG_L		s0, (t0)
+	bne		s0, zero,1b
+
+	sync
+	j		s1
+	END(kexec_smp_wait)
+#endif
+
+#ifdef __mips64
+       /* all PTR's must be aligned to 8 byte in 64-bit mode */
+       .align  3
+#endif
+
+/* All parameters to new kernel are passed in registers a0-a3.
+ * kexec_args[0..3] are uses to prepare register values.
+ */
+
+EXPORT(kexec_args)
+arg0:	PTR		0x0
+arg1:	PTR		0x0
+arg2:	PTR		0x0
+arg3:	PTR		0x0
+	.size	kexec_args,PTRSIZE*4
+
+#ifdef CONFIG_SMP
+/*
+ * Secondary CPUs may have different kernel parameters in
+ * their registers a0-a3. secondary_kexec_args[0..3] are used
+ * to prepare register values.
+ */
+EXPORT(secondary_kexec_args)
+s_arg0:	PTR		0x0
+s_arg1:	PTR		0x0
+s_arg2:	PTR		0x0
+s_arg3:	PTR		0x0
+	.size	secondary_kexec_args,PTRSIZE*4
+kexec_flag:
+	LONG		0x1
+
+#endif
+
+EXPORT(kexec_start_address)
 	PTR		0x0
 	.size		kexec_start_address, PTRSIZE
 
-kexec_indirection_page:
-	EXPORT(kexec_indirection_page)
+EXPORT(kexec_indirection_page)
 	PTR		0
 	.size		kexec_indirection_page, PTRSIZE
-
-relocate_new_kernel_end:
-
-relocate_new_kernel_size:
-	EXPORT(relocate_new_kernel_size)
-	PTR		relocate_new_kernel_end - relocate_new_kernel
-	.size		relocate_new_kernel_size, PTRSIZE
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 058e964..8bec715 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -22,6 +22,7 @@
 #include <linux/console.h>
 #include <linux/pfn.h>
 #include <linux/debugfs.h>
+#include <linux/kexec.h>
 
 #include <asm/addrspace.h>
 #include <asm/bootinfo.h>
@@ -523,12 +524,62 @@
 	}
 
 	bootmem_init();
+#ifdef CONFIG_KEXEC
+	if (crashk_res.start != crashk_res.end)
+		reserve_bootmem(crashk_res.start,
+			crashk_res.end - crashk_res.start + 1,
+			BOOTMEM_DEFAULT);
+#endif
 	device_tree_init();
 	sparse_init();
 	plat_swiotlb_setup();
 	paging_init();
 }
 
+#ifdef CONFIG_KEXEC
+static inline unsigned long long get_total_mem(void)
+{
+	unsigned long long total;
+	total = max_pfn - min_low_pfn;
+	return total << PAGE_SHIFT;
+}
+
+static void __init mips_parse_crashkernel(void)
+{
+	unsigned long long total_mem;
+	unsigned long long crash_size, crash_base;
+	int ret;
+
+	total_mem = get_total_mem();
+	ret = parse_crashkernel(boot_command_line, total_mem,
+			&crash_size, &crash_base);
+	if (ret != 0 || crash_size <= 0)
+		return;
+
+	crashk_res.start = crash_base;
+	crashk_res.end   = crash_base + crash_size - 1;
+}
+static void __init request_crashkernel(struct resource *res)
+{
+	int ret;
+
+	ret = request_resource(res, &crashk_res);
+	if (!ret)
+		printk(KERN_INFO "Reserving %ldMB of memory at %ldMB "
+			"for crashkernel\n",
+			(unsigned long)((crashk_res.end -
+				crashk_res.start + 1) >> 20),
+			(unsigned long)(crashk_res.start  >> 20));
+}
+#else
+static void __init mips_parse_crashkernel(void)
+{
+}
+static void __init request_crashkernel(struct resource *res)
+{
+}
+#endif
+
 static void __init resource_init(void)
 {
 	int i;
@@ -544,6 +595,8 @@
 	/*
 	 * Request address space for all standard RAM.
 	 */
+	mips_parse_crashkernel();
+
 	for (i = 0; i < boot_mem_map.nr_map; i++) {
 		struct resource *res;
 		unsigned long start, end;
@@ -580,6 +633,7 @@
 		 */
 		request_resource(res, &code_resource);
 		request_resource(res, &data_resource);
+		request_crashkernel(res);
 	}
 }
 
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index 32c1e95..474a26b 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -433,3 +433,21 @@
 
 EXPORT_SYMBOL(flush_tlb_page);
 EXPORT_SYMBOL(flush_tlb_one);
+
+#if defined(CONFIG_KEXEC)
+void (*dump_ipi_function_ptr)(void *) = NULL;
+void dump_send_ipi(void (*dump_ipi_callback)(void *))
+{
+	int i;
+	int cpu = smp_processor_id();
+
+	dump_ipi_function_ptr = dump_ipi_callback;
+	smp_mb();
+	for_each_online_cpu(i)
+		if (i != cpu)
+			core_send_ipi(i, SMP_DUMP);
+
+}
+EXPORT_SYMBOL(dump_send_ipi);
+#endif
+
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index 924da5e..e25f020 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -50,6 +50,10 @@
 		*(.text.*)
 		*(.fixup)
 		*(.gnu.warning)
+		__start___kexec_relocate = .;
+		KEEP(*(.kexec.relocate))
+		KEEP(*(.__kexec.relocate))
+		__end___kexec_relocate = .;
 	} :text = 0
 	_etext = .;	/* End of text section */
 
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
index 2a7c74f..bb0dea1 100644
--- a/arch/mips/lib/Makefile
+++ b/arch/mips/lib/Makefile
@@ -3,7 +3,7 @@
 #
 
 lib-y	+= csum_partial.o delay.o memcpy.o memcpy-inatomic.o memset.o \
-	   strlen_user.o strncpy_user.o strnlen_user.o uncached.o
+	   strlen_user.o strncpy_user.o strnlen_user.o uncached.o memcmp.o
 
 obj-y			+= iomap.o
 obj-$(CONFIG_PCI)	+= iomap-pci.o
diff --git a/arch/mips/lib/memcmp.c b/arch/mips/lib/memcmp.c
new file mode 100644
index 0000000..35ef164
--- /dev/null
+++ b/arch/mips/lib/memcmp.c
@@ -0,0 +1,22 @@
+/*
+ *  copied from linux/lib/string.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+
+#undef memcmp
+int memcmp(const void *cs, const void *ct, size_t count)
+{
+	const unsigned char *su1, *su2;
+	int res = 0;
+
+	for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
+		if ((res = *su1 - *su2) != 0)
+			break;
+	return res;
+}
+EXPORT_SYMBOL(memcmp);
+
diff --git a/arch/mips/math-emu/Makefile b/arch/mips/math-emu/Makefile
index 9660723..62dab5a 100644
--- a/arch/mips/math-emu/Makefile
+++ b/arch/mips/math-emu/Makefile
@@ -2,11 +2,13 @@
 # Makefile for the Linux/MIPS kernel FPU emulation.
 #
 
-obj-y	:= cp1emu.o ieee754m.o ieee754d.o ieee754dp.o ieee754sp.o ieee754.o \
+obj-y	:=	kernel_linkage.o dsemul.o cp1emu.o
+
+obj-$(CONFIG_MIPS_FPU_EMU)	+= ieee754m.o ieee754d.o ieee754dp.o ieee754sp.o ieee754.o \
 	   ieee754xcpt.o dp_frexp.o dp_modf.o dp_div.o dp_mul.o dp_sub.o \
 	   dp_add.o dp_fsp.o dp_cmp.o dp_logb.o dp_scalb.o dp_simple.o \
 	   dp_tint.o dp_fint.o dp_tlong.o dp_flong.o sp_frexp.o sp_modf.o \
 	   sp_div.o sp_mul.o sp_sub.o sp_add.o sp_fdp.o sp_cmp.o sp_logb.o \
 	   sp_scalb.o sp_simple.o sp_tint.o sp_fint.o sp_tlong.o sp_flong.o \
-	   dp_sqrt.o sp_sqrt.o kernel_linkage.o dsemul.o
+	   dp_sqrt.o sp_sqrt.o
 
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index a03bf00..45c59e3 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -58,7 +58,11 @@
 #define __mips 4
 
 /* Function which emulates a floating point instruction. */
+#ifdef CONFIG_DEBUG_FS
+DEFINE_PER_CPU(struct mips_fpu_emulator_stats, fpuemustats);
+#endif
 
+#ifdef CONFIG_MIPS_FPU_EMU
 static int fpu_emu(struct pt_regs *, struct mips_fpu_struct *,
 	mips_instruction);
 
@@ -69,10 +73,6 @@
 
 /* Further private data for which no space exists in mips_fpu_struct */
 
-#ifdef CONFIG_DEBUG_FS
-DEFINE_PER_CPU(struct mips_fpu_emulator_stats, fpuemustats);
-#endif
-
 /* Control registers */
 
 #define FPCREG_RID	0	/* $0  = revision id */
@@ -1360,7 +1360,6 @@
 
 	return sig;
 }
-
 #ifdef CONFIG_DEBUG_FS
 
 static int fpuemu_stat_get(void *data, u64 *val)
@@ -1409,4 +1408,11 @@
 	return 0;
 }
 __initcall(debugfs_fpuemu);
-#endif
+#endif /* CONFIG_DEBUGFS */
+#else
+int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
+        int has_fpu)
+{
+	return 0;
+}
+#endif /* CONFIG_MIPS_FPU_EMU */
diff --git a/arch/mips/math-emu/dsemul.c b/arch/mips/math-emu/dsemul.c
index 3c4a8c5..410b27e 100644
--- a/arch/mips/math-emu/dsemul.c
+++ b/arch/mips/math-emu/dsemul.c
@@ -109,6 +109,7 @@
 	return SIGILL;		/* force out of emulation loop */
 }
 
+#ifdef CONFIG_MIPS_FPU_EMU
 int do_dsemulret(struct pt_regs *xcp)
 {
 	struct emuframe __user *fr;
@@ -165,3 +166,9 @@
 
 	return 1;
 }
+#else
+int do_dsemulret(struct pt_regs *xcp)
+{
+	return 0;
+}
+#endif /* CONFIG_MIPS_FPU_EMU */
diff --git a/arch/mips/math-emu/kernel_linkage.c b/arch/mips/math-emu/kernel_linkage.c
index 52e6c58..c1d923e 100644
--- a/arch/mips/math-emu/kernel_linkage.c
+++ b/arch/mips/math-emu/kernel_linkage.c
@@ -29,6 +29,7 @@
 
 #define SIGNALLING_NAN 0x7ff800007ff80000LL
 
+#ifdef CONFIG_MIPS_FPU_EMU
 void fpu_emulator_init_fpu(void)
 {
 	static int first = 1;
@@ -112,4 +113,36 @@
 
 	return err;
 }
-#endif
+#endif	/* CONFIG_64BIT */
+#else
+
+void fpu_emulator_init_fpu(void)
+{
+	printk(KERN_INFO "FPU emulator disabled, make sure your toolchain"
+		"was compiled with software floating point support (soft-float)\n");
+	return;
+}
+
+int fpu_emulator_save_context(struct sigcontext __user *sc)
+{
+	return 0;
+}
+
+int fpu_emulator_restore_context(struct sigcontext __user *sc)
+{
+	return 0;
+}
+
+int fpu_emulator_save_context32(struct sigcontext32 __user *sc)
+{
+	return 0;
+}
+
+int fpu_emulator_restore_context32(struct sigcontext32 __user *sc)
+{
+	return 0;
+}
+
+#ifdef CONFIG_64BIT
+#endif	/* CONFIG_64BIT */
+#endif /* CONFIG_MIPS_FPU_EMU */
diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c
index 829320c..ef83ef1 100644
--- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c
@@ -39,6 +39,7 @@
 void (*__invalidate_kernel_vmap_range)(unsigned long vaddr, int size);
 
 EXPORT_SYMBOL_GPL(__flush_kernel_vmap_range);
+EXPORT_SYMBOL(__flush_cache_all);
 
 /* MIPS specific cache operations */
 void (*flush_cache_sigtramp)(unsigned long addr);
diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c
index 54759f1..86cf234 100644
--- a/arch/mips/oprofile/op_model_mipsxx.c
+++ b/arch/mips/oprofile/op_model_mipsxx.c
@@ -298,6 +298,11 @@
 	}
 }
 
+static irqreturn_t mipsxx_perfcount_int(int irq, void *dev_id)
+{
+	return mipsxx_perfcount_handler();
+}
+
 static int __init mipsxx_init(void)
 {
 	int counters;
@@ -374,6 +379,10 @@
 	save_perf_irq = perf_irq;
 	perf_irq = mipsxx_perfcount_handler;
 
+	if (cp0_perfcount_irq >= 0)
+		return request_irq(cp0_perfcount_irq, mipsxx_perfcount_int,
+			IRQF_SHARED, "Perfcounter", save_perf_irq);
+
 	return 0;
 }
 
@@ -381,6 +390,9 @@
 {
 	int counters = op_model_mipsxx_ops.num_counters;
 
+	if (cp0_perfcount_irq >= 0)
+		free_irq(cp0_perfcount_irq, save_perf_irq);
+
 	counters = counters_per_cpu_to_total(counters);
 	on_each_cpu(reset_counters, (void *)(long)counters, 1);
 
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index b8b105c..368f04c 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -94,7 +94,6 @@
 endif
 endif
 
-KBUILD_LDFLAGS_MODULE += arch/powerpc/lib/crtsavres.o
 
 ifeq ($(CONFIG_TUNE_CELL),y)
 	KBUILD_CFLAGS += $(call cc-option,-mtune=cell)
@@ -130,7 +129,8 @@
 KBUILD_CFLAGS		+= -mno-sched-epilog
 endif
 
-cpu-as-$(CONFIG_4xx)		+= -Wa,-m405
+cpu-as-$(CONFIG_40x)		+= -Wa,-m405
+cpu-as-$(CONFIG_44x)		+= -Wa,-m440
 cpu-as-$(CONFIG_ALTIVEC)	+= -Wa,-maltivec
 cpu-as-$(CONFIG_E500)		+= -Wa,-me500
 cpu-as-$(CONFIG_E200)		+= -Wa,-me200
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index 8844a17..0bfa694 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -38,10 +38,10 @@
 DTC_FLAGS	?= -p 1024
 
 $(obj)/4xx.o: BOOTCFLAGS += -mcpu=405
-$(obj)/ebony.o: BOOTCFLAGS += -mcpu=405
+$(obj)/ebony.o: BOOTCFLAGS += -mcpu=440
 $(obj)/cuboot-hotfoot.o: BOOTCFLAGS += -mcpu=405
-$(obj)/cuboot-taishan.o: BOOTCFLAGS += -mcpu=405
-$(obj)/cuboot-katmai.o: BOOTCFLAGS += -mcpu=405
+$(obj)/cuboot-taishan.o: BOOTCFLAGS += -mcpu=440
+$(obj)/cuboot-katmai.o: BOOTCFLAGS += -mcpu=440
 $(obj)/cuboot-acadia.o: BOOTCFLAGS += -mcpu=405
 $(obj)/treeboot-walnut.o: BOOTCFLAGS += -mcpu=405
 $(obj)/treeboot-iss4xx.o: BOOTCFLAGS += -mcpu=405
diff --git a/arch/sparc/kernel/ldc.c b/arch/sparc/kernel/ldc.c
index 435e406..81d92fc 100644
--- a/arch/sparc/kernel/ldc.c
+++ b/arch/sparc/kernel/ldc.c
@@ -1250,14 +1250,12 @@
 	snprintf(lp->rx_irq_name, LDC_IRQ_NAME_MAX, "%s RX", name);
 	snprintf(lp->tx_irq_name, LDC_IRQ_NAME_MAX, "%s TX", name);
 
-	err = request_irq(lp->cfg.rx_irq, ldc_rx,
-			  IRQF_SAMPLE_RANDOM | IRQF_DISABLED,
+	err = request_irq(lp->cfg.rx_irq, ldc_rx, IRQF_DISABLED,
 			  lp->rx_irq_name, lp);
 	if (err)
 		return err;
 
-	err = request_irq(lp->cfg.tx_irq, ldc_tx,
-			  IRQF_SAMPLE_RANDOM | IRQF_DISABLED,
+	err = request_irq(lp->cfg.tx_irq, ldc_tx, IRQF_DISABLED,
 			  lp->tx_irq_name, lp);
 	if (err) {
 		free_irq(lp->cfg.rx_irq, lp);
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index c1cf220..fb54aa1 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -371,7 +371,7 @@
 int line_setup_irq(int fd, int input, int output, struct line *line, void *data)
 {
 	const struct line_driver *driver = line->driver;
-	int err = 0, flags = IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM;
+	int err = 0, flags = IRQF_DISABLED | IRQF_SHARED;
 
 	if (input)
 		err = um_request_irq(driver->read_irq, fd, IRQ_READ,
@@ -807,7 +807,7 @@
 				   .stack	= stack });
 
 	if (um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt,
-			   IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
+			   IRQF_DISABLED | IRQF_SHARED,
 			   "winch", winch) < 0) {
 		printk(KERN_ERR "register_winch_irq - failed to register "
 		       "IRQ\n");
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index c70e047..b92e599 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -773,7 +773,7 @@
 	register_reboot_notifier(&reboot_notifier);
 
 	err = um_request_irq(MCONSOLE_IRQ, sock, IRQ_READ, mconsole_interrupt,
-			     IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
+			     IRQF_DISABLED | IRQF_SHARED,
 			     "mconsole", (void *)sock);
 	if (err) {
 		printk(KERN_ERR "Failed to get IRQ for management console\n");
diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c
index a11573b..e10bd6b 100644
--- a/arch/um/drivers/port_kern.c
+++ b/arch/um/drivers/port_kern.c
@@ -100,7 +100,7 @@
 		  .port 	= port });
 
 	if (um_request_irq(TELNETD_IRQ, socket[0], IRQ_READ, pipe_interrupt,
-			  IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
+			  IRQF_DISABLED | IRQF_SHARED,
 			  "telnetd", conn)) {
 		printk(KERN_ERR "port_accept : failed to get IRQ for "
 		       "telnetd\n");
@@ -184,7 +184,7 @@
 	}
 
 	if (um_request_irq(ACCEPT_IRQ, fd, IRQ_READ, port_interrupt,
-			  IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
+			  IRQF_DISABLED | IRQF_SHARED,
 			  "port", port)) {
 		printk(KERN_ERR "Failed to get IRQ for port %d\n", port_num);
 		goto out_close;
diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c
index 981085a..04cdccb 100644
--- a/arch/um/drivers/random.c
+++ b/arch/um/drivers/random.c
@@ -131,8 +131,7 @@
 	random_fd = err;
 
 	err = um_request_irq(RANDOM_IRQ, random_fd, IRQ_READ, random_interrupt,
-			     IRQF_DISABLED | IRQF_SAMPLE_RANDOM, "random",
-			     NULL);
+			     IRQF_DISABLED, "random", NULL);
 	if (err)
 		goto err_out_cleanup_hw;
 
diff --git a/arch/um/drivers/xterm_kern.c b/arch/um/drivers/xterm_kern.c
index b646bcc..61ef7e0 100644
--- a/arch/um/drivers/xterm_kern.c
+++ b/arch/um/drivers/xterm_kern.c
@@ -50,8 +50,7 @@
 	init_completion(&data->ready);
 
 	err = um_request_irq(XTERM_IRQ, socket, IRQ_READ, xterm_interrupt,
-			     IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
-			     "xterm", data);
+			     IRQF_DISABLED | IRQF_SHARED, "xterm", data);
 	if (err) {
 		printk(KERN_ERR "xterm_fd : failed to get IRQ for xterm, "
 		       "err = %d\n",  err);
diff --git a/arch/um/kernel/sigio.c b/arch/um/kernel/sigio.c
index 2b272b6..82ae058 100644
--- a/arch/um/kernel/sigio.c
+++ b/arch/um/kernel/sigio.c
@@ -25,8 +25,7 @@
 	int err;
 
 	err = um_request_irq(SIGIO_WRITE_IRQ, fd, IRQ_READ, sigio_interrupt,
-			     IRQF_DISABLED|IRQF_SAMPLE_RANDOM, "write sigio",
-			     NULL);
+			     IRQF_DISABLED, "write sigio", NULL);
 	if (err) {
 		printk(KERN_ERR "write_sigio_irq : um_request_irq failed, "
 		       "err = %d\n", err);
diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c
index b685296..dd52e74 100644
--- a/arch/x86/tools/relocs.c
+++ b/arch/x86/tools/relocs.c
@@ -10,7 +10,18 @@
 #define USE_BSD
 #include <endian.h>
 #include <regex.h>
-#include <tools/le_byteshift.h>
+
+static inline void __put_unaligned_le16(uint16_t val, uint8_t *p)
+{
+	*p++ = val;
+	*p++ = val >> 8;
+}
+
+static inline void put_unaligned_le32(uint32_t val, uint8_t *p)
+{
+	__put_unaligned_le16(val >> 16, p + 2);
+	__put_unaligned_le16(val, p);
+}
 
 static void die(char *fmt, ...);
 
diff --git a/block/partition-generic.c b/block/partition-generic.c
index 6df5d69..d9942e6 100644
--- a/block/partition-generic.c
+++ b/block/partition-generic.c
@@ -546,6 +546,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL(rescan_partitions);
 
 unsigned char *read_dev_sector(struct block_device *bdev, sector_t n, Sector *p)
 {
diff --git a/crypto/Kconfig b/crypto/Kconfig
index e6cfe1a..c037f3b 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -31,7 +31,7 @@
 	  this is.
 
 config CRYPTO_ALGAPI
-	tristate
+	tristate "ALGAPI"
 	select CRYPTO_ALGAPI2
 	help
 	  This option provides the API for cryptographic algorithms.
@@ -40,7 +40,7 @@
 	tristate
 
 config CRYPTO_AEAD
-	tristate
+	tristate "AEAD"
 	select CRYPTO_AEAD2
 	select CRYPTO_ALGAPI
 
@@ -49,7 +49,7 @@
 	select CRYPTO_ALGAPI2
 
 config CRYPTO_BLKCIPHER
-	tristate
+	tristate "BLKCIPHER"
 	select CRYPTO_BLKCIPHER2
 	select CRYPTO_ALGAPI
 
@@ -60,7 +60,7 @@
 	select CRYPTO_WORKQUEUE
 
 config CRYPTO_HASH
-	tristate
+	tristate "HASH"
 	select CRYPTO_HASH2
 	select CRYPTO_ALGAPI
 
@@ -69,7 +69,7 @@
 	select CRYPTO_ALGAPI2
 
 config CRYPTO_RNG
-	tristate
+	tristate "RNG"
 	select CRYPTO_RNG2
 	select CRYPTO_ALGAPI
 
@@ -924,6 +924,13 @@
 	help
 	  This is the LZO algorithm.
 
+config CRYPTO_XZ
+	tristate "XZ compression algorithm"
+	select CRYPTO_ALGAPI
+	select XZ_DEC
+	help
+	  This is the XZ algorithm. Only decompression is supported for now.
+
 comment "Random Number Generation"
 
 config CRYPTO_ANSI_CPRNG
@@ -961,3 +968,6 @@
 source "drivers/crypto/Kconfig"
 
 endif	# if CRYPTO
+
+source "crypto/ocf/Kconfig"
+
diff --git a/crypto/Makefile b/crypto/Makefile
index f638063..7ba166a 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -82,6 +82,7 @@
 obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o
 obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o authencesn.o
 obj-$(CONFIG_CRYPTO_LZO) += lzo.o
+obj-$(CONFIG_CRYPTO_XZ) += xz.o
 obj-$(CONFIG_CRYPTO_RNG2) += rng.o
 obj-$(CONFIG_CRYPTO_RNG2) += krng.o
 obj-$(CONFIG_CRYPTO_ANSI_CPRNG) += ansi_cprng.o
@@ -91,6 +92,8 @@
 obj-$(CONFIG_CRYPTO_USER_API_HASH) += algif_hash.o
 obj-$(CONFIG_CRYPTO_USER_API_SKCIPHER) += algif_skcipher.o
 
+obj-$(CONFIG_OCF_OCF) += ocf/
+
 #
 # generic algorithms and the async_tx api
 #
diff --git a/crypto/xz.c b/crypto/xz.c
new file mode 100644
index 0000000..2c00cfd
--- /dev/null
+++ b/crypto/xz.c
@@ -0,0 +1,117 @@
+/*
+ * Cryptographic API.
+ *
+ * XZ decompression support.
+ *
+ * Copyright (c) 2012 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/crypto.h>
+#include <linux/xz.h>
+#include <linux/interrupt.h>
+#include <linux/mm.h>
+#include <linux/net.h>
+
+struct xz_comp_ctx {
+	struct xz_dec	*decomp_state;
+	struct xz_buf	decomp_buf;
+};
+
+static int crypto_xz_decomp_init(struct xz_comp_ctx *ctx)
+{
+	ctx->decomp_state = xz_dec_init(XZ_SINGLE, 0);
+	if (!ctx->decomp_state)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static void crypto_xz_decomp_exit(struct xz_comp_ctx *ctx)
+{
+	xz_dec_end(ctx->decomp_state);
+}
+
+static int crypto_xz_init(struct crypto_tfm *tfm)
+{
+	struct xz_comp_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	return crypto_xz_decomp_init(ctx);
+}
+
+static void crypto_xz_exit(struct crypto_tfm *tfm)
+{
+	struct xz_comp_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	crypto_xz_decomp_exit(ctx);
+}
+
+static int crypto_xz_compress(struct crypto_tfm *tfm, const u8 *src,
+			      unsigned int slen, u8 *dst, unsigned int *dlen)
+{
+	return -EOPNOTSUPP;
+}
+
+static int crypto_xz_decompress(struct crypto_tfm *tfm, const u8 *src,
+				unsigned int slen, u8 *dst, unsigned int *dlen)
+{
+	struct xz_comp_ctx *dctx = crypto_tfm_ctx(tfm);
+	struct xz_buf *xz_buf = &dctx->decomp_buf;
+	int ret;
+
+	memset(xz_buf, '\0', sizeof(struct xz_buf));
+
+	xz_buf->in = (u8 *) src;
+	xz_buf->in_pos = 0;
+	xz_buf->in_size = slen;
+	xz_buf->out = (u8 *) dst;
+	xz_buf->out_pos = 0;
+	xz_buf->out_size = *dlen;
+
+	ret = xz_dec_run(dctx->decomp_state, xz_buf);
+	if (ret != XZ_STREAM_END) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	*dlen = xz_buf->out_pos;
+	ret = 0;
+
+out:
+	return ret;
+}
+
+static struct crypto_alg crypto_xz_alg = {
+	.cra_name		= "xz",
+	.cra_flags		= CRYPTO_ALG_TYPE_COMPRESS,
+	.cra_ctxsize		= sizeof(struct xz_comp_ctx),
+	.cra_module		= THIS_MODULE,
+	.cra_list		= LIST_HEAD_INIT(crypto_xz_alg.cra_list),
+	.cra_init		= crypto_xz_init,
+	.cra_exit		= crypto_xz_exit,
+	.cra_u			= { .compress = {
+	.coa_compress 		= crypto_xz_compress,
+	.coa_decompress  	= crypto_xz_decompress } }
+};
+
+static int __init crypto_xz_mod_init(void)
+{
+	return crypto_register_alg(&crypto_xz_alg);
+}
+
+static void __exit crypto_xz_mod_exit(void)
+{
+	crypto_unregister_alg(&crypto_xz_alg);
+}
+
+module_init(crypto_xz_mod_init);
+module_exit(crypto_xz_mod_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Crypto XZ decompression support");
+MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 5afe5d1..5215770 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -60,6 +60,8 @@
 
 source "drivers/gpio/Kconfig"
 
+source "drivers/pwm/Kconfig"
+
 source "drivers/w1/Kconfig"
 
 source "drivers/power/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index c07be02..34503cc 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -8,6 +8,7 @@
 # GPIO must come after pinctrl as gpios may need to mux pins etc
 obj-y				+= pinctrl/
 obj-y				+= gpio/
+obj-$(CONFIG_GENERIC_PWM)	+= pwm/
 obj-$(CONFIG_PCI)		+= pci/
 obj-$(CONFIG_PARISC)		+= parisc/
 obj-$(CONFIG_RAPIDIO)		+= rapidio/
diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c
index e8cd652..0a1cbd0 100644
--- a/drivers/atm/solos-pci.c
+++ b/drivers/atm/solos-pci.c
@@ -42,7 +42,8 @@
 #include <linux/swab.h>
 #include <linux/slab.h>
 
-#define VERSION "0.07"
+#define VERSION "1.04"
+#define DRIVER_VERSION 0x01
 #define PTAG "solos-pci"
 
 #define CONFIG_RAM_SIZE	128
@@ -56,16 +57,21 @@
 #define FLASH_BUSY	0x60
 #define FPGA_MODE	0x5C
 #define FLASH_MODE	0x58
+#define GPIO_STATUS	0x54
+#define DRIVER_VER	0x50
 #define TX_DMA_ADDR(port)	(0x40 + (4 * (port)))
 #define RX_DMA_ADDR(port)	(0x30 + (4 * (port)))
 
 #define DATA_RAM_SIZE	32768
 #define BUF_SIZE	2048
 #define OLD_BUF_SIZE	4096 /* For FPGA versions <= 2*/
-#define FPGA_PAGE	528 /* FPGA flash page size*/
-#define SOLOS_PAGE	512 /* Solos flash page size*/
-#define FPGA_BLOCK	(FPGA_PAGE * 8) /* FPGA flash block size*/
-#define SOLOS_BLOCK	(SOLOS_PAGE * 8) /* Solos flash block size*/
+/* Old boards use ATMEL AD45DB161D flash */
+#define ATMEL_FPGA_PAGE	528 /* FPGA flash page size*/
+#define ATMEL_SOLOS_PAGE	512 /* Solos flash page size*/
+#define ATMEL_FPGA_BLOCK	(ATMEL_FPGA_PAGE * 8) /* FPGA block size*/
+#define ATMEL_SOLOS_BLOCK	(ATMEL_SOLOS_PAGE * 8) /* Solos block size*/
+/* Current boards use M25P/M25PE SPI flash */
+#define SPI_FLASH_BLOCK	(256 * 64)
 
 #define RX_BUF(card, nr) ((card->buffers) + (nr)*(card->buffer_size)*2)
 #define TX_BUF(card, nr) ((card->buffers) + (nr)*(card->buffer_size)*2 + (card->buffer_size))
@@ -92,6 +98,7 @@
 };
 
 struct solos_skb_cb {
+	struct completion c;
 	struct atm_vcc *vcc;
 	uint32_t dma_addr;
 };
@@ -122,11 +129,14 @@
 	struct sk_buff_head cli_queue[4];
 	struct sk_buff *tx_skb[4];
 	struct sk_buff *rx_skb[4];
+	unsigned char *dma_bounce;
 	wait_queue_head_t param_wq;
 	wait_queue_head_t fw_wq;
 	int using_dma;
+	int dma_alignment;
 	int fpga_version;
 	int buffer_size;
+	int atmel_flash;
 };
 
 
@@ -164,7 +174,6 @@
 static uint32_t fpga_tx(struct solos_card *);
 static irqreturn_t solos_irq(int irq, void *dev_id);
 static struct atm_vcc* find_vcc(struct atm_dev *dev, short vpi, int vci);
-static int list_vccs(int vci);
 static int atm_init(struct solos_card *, struct device *);
 static void atm_remove(struct solos_card *);
 static int send_command(struct solos_card *card, int dev, const char *buf, size_t size);
@@ -452,7 +461,6 @@
 
 	len = skb->len;
 	memcpy(buf, skb->data, len);
-	dev_dbg(&card->dev->dev, "len: %d\n", len);
 
 	kfree_skb(skb);
 	return len;
@@ -499,6 +507,78 @@
 	return err?:count;
 }
 
+struct geos_gpio_attr {
+	struct device_attribute attr;
+	int offset;
+};
+
+#define SOLOS_GPIO_ATTR(_name, _mode, _show, _store, _offset)	\
+	struct geos_gpio_attr gpio_attr_##_name = {		\
+		.attr = __ATTR(_name, _mode, _show, _store),	\
+		.offset = _offset }
+
+static ssize_t geos_gpio_store(struct device *dev, struct device_attribute *attr,
+			       const char *buf, size_t count)
+{
+	struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
+	struct geos_gpio_attr *gattr = container_of(attr, struct geos_gpio_attr, attr);
+	struct solos_card *card = pci_get_drvdata(pdev);
+	uint32_t data32;
+
+	if (count != 1 && (count != 2 || buf[1] != '\n'))
+		return -EINVAL;
+
+	spin_lock_irq(&card->param_queue_lock);
+	data32 = ioread32(card->config_regs + GPIO_STATUS);
+	if (buf[0] == '1') {
+		data32 |= 1 << gattr->offset;
+		iowrite32(data32, card->config_regs + GPIO_STATUS);
+	} else if (buf[0] == '0') {
+		data32 &= ~(1 << gattr->offset);
+		iowrite32(data32, card->config_regs + GPIO_STATUS);
+	} else {
+		count = -EINVAL;
+	}
+	spin_unlock_irq(&card->param_queue_lock);
+	return count;
+}
+
+static ssize_t geos_gpio_show(struct device *dev, struct device_attribute *attr,
+			      char *buf)
+{
+	struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
+	struct geos_gpio_attr *gattr = container_of(attr, struct geos_gpio_attr, attr);
+	struct solos_card *card = pci_get_drvdata(pdev);
+	uint32_t data32;
+
+	data32 = ioread32(card->config_regs + GPIO_STATUS);
+	data32 = (data32 >> gattr->offset) & 1;
+
+	return sprintf(buf, "%d\n", data32);
+}
+
+static ssize_t hardware_show(struct device *dev, struct device_attribute *attr,
+			     char *buf)
+{
+	struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
+	struct geos_gpio_attr *gattr = container_of(attr, struct geos_gpio_attr, attr);
+	struct solos_card *card = pci_get_drvdata(pdev);
+	uint32_t data32;
+
+	data32 = ioread32(card->config_regs + GPIO_STATUS);
+	switch (gattr->offset) {
+	case 0:
+		/* HardwareVersion */
+		data32 = data32 & 0x1F;
+		break;
+	case 1:
+		/* HardwareVariant */
+		data32 = (data32 >> 5) & 0x0F;
+		break;
+	}
+	return sprintf(buf, "%d\n", data32);
+}
+
 static DEVICE_ATTR(console, 0644, console_show, console_store);
 
 
@@ -507,6 +587,14 @@
 
 #include "solos-attrlist.c"
 
+static SOLOS_GPIO_ATTR(GPIO1, 0644, geos_gpio_show, geos_gpio_store, 9);
+static SOLOS_GPIO_ATTR(GPIO2, 0644, geos_gpio_show, geos_gpio_store, 10);
+static SOLOS_GPIO_ATTR(GPIO3, 0644, geos_gpio_show, geos_gpio_store, 11);
+static SOLOS_GPIO_ATTR(GPIO4, 0644, geos_gpio_show, geos_gpio_store, 12);
+static SOLOS_GPIO_ATTR(GPIO5, 0644, geos_gpio_show, geos_gpio_store, 13);
+static SOLOS_GPIO_ATTR(PushButton, 0444, geos_gpio_show, NULL, 14);
+static SOLOS_GPIO_ATTR(HardwareVersion, 0444, hardware_show, NULL, 0);
+static SOLOS_GPIO_ATTR(HardwareVariant, 0444, hardware_show, NULL, 1);
 #undef SOLOS_ATTR_RO
 #undef SOLOS_ATTR_RW
 
@@ -523,6 +611,23 @@
 	.name = "parameters",
 };
 
+static struct attribute *gpio_attrs[] = {
+	&gpio_attr_GPIO1.attr.attr,
+	&gpio_attr_GPIO2.attr.attr,
+	&gpio_attr_GPIO3.attr.attr,
+	&gpio_attr_GPIO4.attr.attr,
+	&gpio_attr_GPIO5.attr.attr,
+	&gpio_attr_PushButton.attr.attr,
+	&gpio_attr_HardwareVersion.attr.attr,
+	&gpio_attr_HardwareVariant.attr.attr,
+	NULL
+};
+
+static struct attribute_group gpio_attr_group = {
+	.attrs = gpio_attrs,
+	.name = "gpio",
+};
+
 static int flash_upgrade(struct solos_card *card, int chip)
 {
 	const struct firmware *fw;
@@ -534,16 +639,25 @@
 	switch (chip) {
 	case 0:
 		fw_name = "solos-FPGA.bin";
-		blocksize = FPGA_BLOCK;
+		if (card->atmel_flash)
+			blocksize = ATMEL_FPGA_BLOCK;
+		else
+			blocksize = SPI_FLASH_BLOCK;
 		break;
 	case 1:
 		fw_name = "solos-Firmware.bin";
-		blocksize = SOLOS_BLOCK;
+		if (card->atmel_flash)
+			blocksize = ATMEL_SOLOS_BLOCK;
+		else
+			blocksize = SPI_FLASH_BLOCK;
 		break;
 	case 2:
 		if (card->fpga_version > LEGACY_BUFFERS){
 			fw_name = "solos-db-FPGA.bin";
-			blocksize = FPGA_BLOCK;
+			if (card->atmel_flash)
+				blocksize = ATMEL_FPGA_BLOCK;
+			else
+				blocksize = SPI_FLASH_BLOCK;
 		} else {
 			dev_info(&card->dev->dev, "FPGA version doesn't support"
 					" daughter board upgrades\n");
@@ -553,7 +667,10 @@
 	case 3:
 		if (card->fpga_version > LEGACY_BUFFERS){
 			fw_name = "solos-Firmware.bin";
-			blocksize = SOLOS_BLOCK;
+			if (card->atmel_flash)
+				blocksize = ATMEL_SOLOS_BLOCK;
+			else
+				blocksize = SPI_FLASH_BLOCK;
 		} else {
 			dev_info(&card->dev->dev, "FPGA version doesn't support"
 					" daughter board upgrades\n");
@@ -569,6 +686,9 @@
 
 	dev_info(&card->dev->dev, "Flash upgrade starting\n");
 
+	/* New FPGAs require driver version before permitting flash upgrades */
+	iowrite32(DRIVER_VERSION, card->config_regs + DRIVER_VER);
+
 	numblocks = fw->size / blocksize;
 	dev_info(&card->dev->dev, "Firmware size: %zd\n", fw->size);
 	dev_info(&card->dev->dev, "Number of blocks: %d\n", numblocks);
@@ -598,9 +718,13 @@
 		/* dev_info(&card->dev->dev, "Set FPGA Flash mode to Block Write\n"); */
 		iowrite32(((chip * 2) + 1), card->config_regs + FLASH_MODE);
 
-		/* Copy block to buffer, swapping each 16 bits */
+		/* Copy block to buffer, swapping each 16 bits for Atmel flash */
 		for(i = 0; i < blocksize; i += 4) {
-			uint32_t word = swahb32p((uint32_t *)(fw->data + offset + i));
+			uint32_t word;
+			if (card->atmel_flash)
+				word = swahb32p((uint32_t *)(fw->data + offset + i));
+			else
+				word = *(uint32_t *)(fw->data + offset + i);
 			if(card->fpga_version > LEGACY_BUFFERS)
 				iowrite32(word, FLASH_BUF + i);
 			else
@@ -710,7 +834,8 @@
 						dev_warn(&card->dev->dev, "Received packet for unknown VPI.VCI %d.%d on port %d\n",
 							 le16_to_cpu(header->vpi), le16_to_cpu(header->vci),
 							 port);
-					continue;
+					dev_kfree_skb_any(skb);
+					break;
 				}
 				atm_charge(vcc, skb->truesize);
 				vcc->push(vcc, skb);
@@ -790,44 +915,6 @@
 	return vcc;
 }
 
-static int list_vccs(int vci)
-{
-	struct hlist_head *head;
-	struct atm_vcc *vcc;
-	struct hlist_node *node;
-	struct sock *s;
-	int num_found = 0;
-	int i;
-
-	read_lock(&vcc_sklist_lock);
-	if (vci != 0){
-		head = &vcc_hash[vci & (VCC_HTABLE_SIZE -1)];
-		sk_for_each(s, node, head) {
-			num_found ++;
-			vcc = atm_sk(s);
-			printk(KERN_DEBUG "Device: %d Vpi: %d Vci: %d\n",
-			       vcc->dev->number,
-			       vcc->vpi,
-			       vcc->vci);
-		}
-	} else {
-		for(i = 0; i < VCC_HTABLE_SIZE; i++){
-			head = &vcc_hash[i];
-			sk_for_each(s, node, head) {
-				num_found ++;
-				vcc = atm_sk(s);
-				printk(KERN_DEBUG "Device: %d Vpi: %d Vci: %d\n",
-				       vcc->dev->number,
-				       vcc->vpi,
-				       vcc->vci);
-			}
-		}
-	}
-	read_unlock(&vcc_sklist_lock);
-	return num_found;
-}
-
-
 static int popen(struct atm_vcc *vcc)
 {
 	struct solos_card *card = vcc->dev->dev_data;
@@ -840,7 +927,7 @@
 		return -EINVAL;
 	}
 
-	skb = alloc_skb(sizeof(*header), GFP_ATOMIC);
+	skb = alloc_skb(sizeof(*header), GFP_KERNEL);
 	if (!skb) {
 		if (net_ratelimit())
 			dev_warn(&card->dev->dev, "Failed to allocate sk_buff in popen()\n");
@@ -857,8 +944,6 @@
 
 	set_bit(ATM_VF_ADDR, &vcc->flags);
 	set_bit(ATM_VF_READY, &vcc->flags);
-	list_vccs(0);
-
 
 	return 0;
 }
@@ -866,10 +951,21 @@
 static void pclose(struct atm_vcc *vcc)
 {
 	struct solos_card *card = vcc->dev->dev_data;
-	struct sk_buff *skb;
+	unsigned char port = SOLOS_CHAN(vcc->dev);
+	struct sk_buff *skb, *tmpskb;
 	struct pkt_hdr *header;
 
-	skb = alloc_skb(sizeof(*header), GFP_ATOMIC);
+	/* Remove any yet-to-be-transmitted packets from the pending queue */
+	spin_lock(&card->tx_queue_lock);
+	skb_queue_walk_safe(&card->tx_queue[port], skb, tmpskb) {
+		if (SKB_CB(skb)->vcc == vcc) {
+			skb_unlink(skb, &card->tx_queue[port]);
+			solos_pop(vcc, skb);
+		}
+	}
+	spin_unlock(&card->tx_queue_lock);
+
+	skb = alloc_skb(sizeof(*header), GFP_KERNEL);
 	if (!skb) {
 		dev_warn(&card->dev->dev, "Failed to allocate sk_buff in pclose()\n");
 		return;
@@ -881,15 +977,21 @@
 	header->vci = cpu_to_le16(vcc->vci);
 	header->type = cpu_to_le16(PKT_PCLOSE);
 
-	fpga_queue(card, SOLOS_CHAN(vcc->dev), skb, NULL);
+	init_completion(&SKB_CB(skb)->c);
 
-	clear_bit(ATM_VF_ADDR, &vcc->flags);
-	clear_bit(ATM_VF_READY, &vcc->flags);
+	fpga_queue(card, port, skb, NULL);
+
+	if (!wait_for_completion_timeout(&SKB_CB(skb)->c, 5 * HZ))
+		dev_warn(&card->dev->dev, "Timeout waiting for VCC close on port %d\n",
+			 port);
 
 	/* Hold up vcc_destroy_socket() (our caller) until solos_bh() in the
 	   tasklet has finished processing any incoming packets (and, more to
 	   the point, using the vcc pointer). */
 	tasklet_unlock_wait(&card->tlet);
+
+	clear_bit(ATM_VF_ADDR, &vcc->flags);
+
 	return;
 }
 
@@ -967,10 +1069,11 @@
 	for (port = 0; tx_pending; tx_pending >>= 1, port++) {
 		if (tx_pending & 1) {
 			struct sk_buff *oldskb = card->tx_skb[port];
-			if (oldskb)
+			if (oldskb) {
 				pci_unmap_single(card->dev, SKB_CB(oldskb)->dma_addr,
 						 oldskb->len, PCI_DMA_TODEVICE);
-
+				card->tx_skb[port] = NULL;
+			}
 			spin_lock(&card->tx_queue_lock);
 			skb = skb_dequeue(&card->tx_queue[port]);
 			if (!skb)
@@ -982,8 +1085,14 @@
 				tx_started |= 1 << port;
 				oldskb = skb; /* We're done with this skb already */
 			} else if (skb && card->using_dma) {
-				SKB_CB(skb)->dma_addr = pci_map_single(card->dev, skb->data,
+				unsigned char *data = skb->data;
+				if ((unsigned long)data & card->dma_alignment) {
+					data = card->dma_bounce + (BUF_SIZE * port);
+					memcpy(data, skb->data, skb->len);
+				}
+				SKB_CB(skb)->dma_addr = pci_map_single(card->dev, data,
 								       skb->len, PCI_DMA_TODEVICE);
+				card->tx_skb[port] = skb;
 				iowrite32(SKB_CB(skb)->dma_addr,
 					  card->config_regs + TX_DMA_ADDR(port));
 			}
@@ -1010,9 +1119,12 @@
 			if (vcc) {
 				atomic_inc(&vcc->stats->tx);
 				solos_pop(vcc, oldskb);
-			} else
+			} else {
+				struct pkt_hdr *header = (void *)oldskb->data;
+				if (le16_to_cpu(header->type) == PKT_PCLOSE)
+					complete(&SKB_CB(oldskb)->c);
 				dev_kfree_skb_irq(oldskb);
-
+			}
 		}
 	}
 	/* For non-DMA TX, write the 'TX start' bit for all four ports simultaneously */
@@ -1152,17 +1264,33 @@
 		db_fpga_upgrade = db_firmware_upgrade = 0;
 	}
 
-	if (card->fpga_version >= DMA_SUPPORTED){
+	/* Stopped using Atmel flash after 0.03-38 */
+	if (fpga_ver < 39)
+		card->atmel_flash = 1;
+	else
+		card->atmel_flash = 0;
+
+	data32 = ioread32(card->config_regs + PORTS);
+	card->nr_ports = (data32 & 0x000000FF);
+
+	if (card->fpga_version >= DMA_SUPPORTED) {
+		pci_set_master(dev);
 		card->using_dma = 1;
+		if (1) { /* All known FPGA versions so far */
+			card->dma_alignment = 3;
+			card->dma_bounce = kmalloc(card->nr_ports * BUF_SIZE, GFP_KERNEL);
+			if (!card->dma_bounce) {
+				dev_warn(&card->dev->dev, "Failed to allocate DMA bounce buffers\n");
+				/* Fallback to MMIO doesn't work */
+				goto out_unmap_both;
+			}
+		}
 	} else {
 		card->using_dma = 0;
 		/* Set RX empty flag for all ports */
 		iowrite32(0xF0, card->config_regs + FLAGS_ADDR);
 	}
 
-	data32 = ioread32(card->config_regs + PORTS);
-	card->nr_ports = (data32 & 0x000000FF);
-
 	pci_set_drvdata(dev, card);
 
 	tasklet_init(&card->tlet, solos_bh, (unsigned long)card);
@@ -1197,6 +1325,10 @@
 	if (err)
 		goto out_free_irq;
 
+	if (card->fpga_version >= DMA_SUPPORTED &&
+	    sysfs_create_group(&card->dev->dev.kobj, &gpio_attr_group))
+		dev_err(&card->dev->dev, "Could not register parameter group for GPIOs\n");
+
 	return 0;
 
  out_free_irq:
@@ -1205,6 +1337,7 @@
 	tasklet_kill(&card->tlet);
 	
  out_unmap_both:
+	kfree(card->dma_bounce);
 	pci_set_drvdata(dev, NULL);
 	pci_iounmap(dev, card->buffers);
  out_unmap_config:
@@ -1246,7 +1379,7 @@
 		card->atmdev[i]->phy_data = (void *)(unsigned long)i;
 		atm_dev_signal_change(card->atmdev[i], ATM_PHY_SIG_FOUND);
 
-		skb = alloc_skb(sizeof(*header), GFP_ATOMIC);
+		skb = alloc_skb(sizeof(*header), GFP_KERNEL);
 		if (!skb) {
 			dev_warn(&card->dev->dev, "Failed to allocate sk_buff in atm_init()\n");
 			continue;
@@ -1307,11 +1440,16 @@
 	iowrite32(1, card->config_regs + FPGA_MODE);
 	(void)ioread32(card->config_regs + FPGA_MODE); 
 
+	if (card->fpga_version >= DMA_SUPPORTED)
+		sysfs_remove_group(&card->dev->dev.kobj, &gpio_attr_group);
+
 	atm_remove(card);
 
 	free_irq(dev->irq, card);
 	tasklet_kill(&card->tlet);
 
+	kfree(card->dma_bounce);
+
 	/* Release device from reset */
 	iowrite32(0, card->config_regs + FPGA_MODE);
 	(void)ioread32(card->config_regs + FPGA_MODE); 
@@ -1343,6 +1481,8 @@
 
 static int __init solos_pci_init(void)
 {
+	BUILD_BUG_ON(sizeof(struct solos_skb_cb) > sizeof(((struct sk_buff *)0)->cb));
+
 	printk(KERN_INFO "Solos PCI Driver Version %s\n", VERSION);
 	return pci_register_driver(&fpga_driver);
 }
diff --git a/drivers/bcma/Kconfig b/drivers/bcma/Kconfig
index c1172da..d878e03 100644
--- a/drivers/bcma/Kconfig
+++ b/drivers/bcma/Kconfig
@@ -17,6 +17,7 @@
 config BCMA_BLOCKIO
 	bool
 	depends on BCMA
+	default y
 
 config BCMA_HOST_PCI_POSSIBLE
 	bool
@@ -29,7 +30,7 @@
 
 config BCMA_DRIVER_PCI_HOSTMODE
 	bool "Driver for PCI core working in hostmode"
-	depends on BCMA && MIPS
+	depends on BCMA && MIPS && BCMA_HOST_PCI
 	help
 	  PCI core hostmode operation (external PCI bus).
 
@@ -46,6 +47,15 @@
 
 	  If unsure, say N
 
+config BCMA_DRIVER_GMAC_CMN
+	bool "BCMA Broadcom GBIT MAC COMMON core driver"
+	depends on BCMA
+	help
+	  Driver for the Broadcom GBIT MAC COMMON core attached to Broadcom
+	  specific Advanced Microcontroller Bus.
+
+	  If unsure, say N
+
 config BCMA_DEBUG
 	bool "BCMA debugging"
 	depends on BCMA
diff --git a/drivers/bcma/Makefile b/drivers/bcma/Makefile
index 82de24e..d13803f 100644
--- a/drivers/bcma/Makefile
+++ b/drivers/bcma/Makefile
@@ -3,6 +3,7 @@
 bcma-y					+= driver_pci.o
 bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE)	+= driver_pci_host.o
 bcma-$(CONFIG_BCMA_DRIVER_MIPS)		+= driver_mips.o
+bcma-$(CONFIG_BCMA_DRIVER_GMAC_CMN)	+= driver_gmac_cmn.o
 bcma-$(CONFIG_BCMA_HOST_PCI)		+= host_pci.o
 bcma-$(CONFIG_BCMA_HOST_SOC)		+= host_soc.o
 obj-$(CONFIG_BCMA)			+= bcma.o
diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h
index 0def898..f6589eb 100644
--- a/drivers/bcma/bcma_private.h
+++ b/drivers/bcma/bcma_private.h
@@ -10,10 +10,19 @@
 
 #define BCMA_CORE_SIZE		0x1000
 
+#define bcma_err(bus, fmt, ...) \
+	pr_err("bus%d: " fmt, (bus)->num, ##__VA_ARGS__)
+#define bcma_warn(bus, fmt, ...) \
+	pr_warn("bus%d: " fmt, (bus)->num, ##__VA_ARGS__)
+#define bcma_info(bus, fmt, ...) \
+	pr_info("bus%d: " fmt, (bus)->num, ##__VA_ARGS__)
+#define bcma_debug(bus, fmt, ...) \
+	pr_debug("bus%d: " fmt, (bus)->num, ##__VA_ARGS__)
+
 struct bcma_bus;
 
 /* main.c */
-int bcma_bus_register(struct bcma_bus *bus);
+int __devinit bcma_bus_register(struct bcma_bus *bus);
 void bcma_bus_unregister(struct bcma_bus *bus);
 int __init bcma_bus_early_register(struct bcma_bus *bus,
 				   struct bcma_device *core_cc,
@@ -48,8 +57,12 @@
 extern void __exit bcma_host_pci_exit(void);
 #endif /* CONFIG_BCMA_HOST_PCI */
 
+/* driver_pci.c */
+u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address);
+
 #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
-void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc);
+bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc);
+void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc);
 #endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */
 
 #endif
diff --git a/drivers/bcma/core.c b/drivers/bcma/core.c
index 893f6e0..63c8b47 100644
--- a/drivers/bcma/core.c
+++ b/drivers/bcma/core.c
@@ -30,6 +30,7 @@
 	udelay(10);
 
 	bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET);
+	bcma_aread32(core, BCMA_RESET_CTL);
 	udelay(1);
 }
 EXPORT_SYMBOL_GPL(bcma_core_disable);
@@ -74,10 +75,10 @@
 			udelay(10);
 		}
 		if (i)
-			pr_err("HT force timeout\n");
+			bcma_err(core->bus, "HT force timeout\n");
 		break;
 	case BCMA_CLKMODE_DYNAMIC:
-		pr_warn("Dynamic clockmode not supported yet!\n");
+		bcma_set32(core, BCMA_CLKCTLST, ~BCMA_CLKCTLST_FORCEHT);
 		break;
 	}
 }
@@ -101,9 +102,9 @@
 			udelay(10);
 		}
 		if (i)
-			pr_err("PLL enable timeout\n");
+			bcma_err(core->bus, "PLL enable timeout\n");
 	} else {
-		pr_warn("Disabling PLL not supported yet!\n");
+		bcma_warn(core->bus, "Disabling PLL not supported yet!\n");
 	}
 }
 EXPORT_SYMBOL_GPL(bcma_core_pll_ctl);
@@ -119,8 +120,8 @@
 		else
 			return BCMA_DMA_TRANSLATION_DMA32_CMT;
 	default:
-		pr_err("DMA translation unknown for host %d\n",
-		       core->bus->hosttype);
+		bcma_err(core->bus, "DMA translation unknown for host %d\n",
+			 core->bus->hosttype);
 	}
 	return BCMA_DMA_TRANSLATION_NONE;
 }
diff --git a/drivers/bcma/driver_chipcommon.c b/drivers/bcma/driver_chipcommon.c
index e9f1b3f..a4c3ebc 100644
--- a/drivers/bcma/driver_chipcommon.c
+++ b/drivers/bcma/driver_chipcommon.c
@@ -44,7 +44,7 @@
 	if (cc->capabilities & BCMA_CC_CAP_PMU)
 		bcma_pmu_init(cc);
 	if (cc->capabilities & BCMA_CC_CAP_PCTL)
-		pr_err("Power control not implemented!\n");
+		bcma_err(cc->core->bus, "Power control not implemented!\n");
 
 	if (cc->core->id.rev >= 16) {
 		if (cc->core->bus->sprom.leddc_on_time &&
@@ -137,8 +137,7 @@
 				       | BCMA_CC_CORECTL_UARTCLKEN);
 		}
 	} else {
-		pr_err("serial not supported on this device ccrev: 0x%x\n",
-		       ccrev);
+		bcma_err(cc->core->bus, "serial not supported on this device ccrev: 0x%x\n", ccrev);
 		return;
 	}
 
diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c
index 800163c..c9a4f46 100644
--- a/drivers/bcma/driver_chipcommon_pmu.c
+++ b/drivers/bcma/driver_chipcommon_pmu.c
@@ -3,7 +3,8 @@
  * ChipCommon Power Management Unit driver
  *
  * Copyright 2009, Michael Buesch <m@bues.ch>
- * Copyright 2007, Broadcom Corporation
+ * Copyright 2007, 2011, Broadcom Corporation
+ * Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de>
  *
  * Licensed under the GNU/GPL. See COPYING for details.
  */
@@ -54,38 +55,19 @@
 }
 EXPORT_SYMBOL_GPL(bcma_chipco_regctl_maskset);
 
-static void bcma_pmu_pll_init(struct bcma_drv_cc *cc)
-{
-	struct bcma_bus *bus = cc->core->bus;
-
-	switch (bus->chipinfo.id) {
-	case 0x4313:
-	case 0x4331:
-	case 43224:
-	case 43225:
-		break;
-	default:
-		pr_err("PLL init unknown for device 0x%04X\n",
-			bus->chipinfo.id);
-	}
-}
-
 static void bcma_pmu_resources_init(struct bcma_drv_cc *cc)
 {
 	struct bcma_bus *bus = cc->core->bus;
 	u32 min_msk = 0, max_msk = 0;
 
 	switch (bus->chipinfo.id) {
-	case 0x4313:
+	case BCMA_CHIP_ID_BCM4313:
 		min_msk = 0x200D;
 		max_msk = 0xFFFF;
 		break;
-	case 43224:
-	case 43225:
-		break;
 	default:
-		pr_err("PMU resource config unknown for device 0x%04X\n",
-			bus->chipinfo.id);
+		bcma_debug(bus, "PMU resource config unknown or not needed for device 0x%04X\n",
+			   bus->chipinfo.id);
 	}
 
 	/* Set the resource masks. */
@@ -93,22 +75,9 @@
 		bcma_cc_write32(cc, BCMA_CC_PMU_MINRES_MSK, min_msk);
 	if (max_msk)
 		bcma_cc_write32(cc, BCMA_CC_PMU_MAXRES_MSK, max_msk);
-}
 
-void bcma_pmu_swreg_init(struct bcma_drv_cc *cc)
-{
-	struct bcma_bus *bus = cc->core->bus;
-
-	switch (bus->chipinfo.id) {
-	case 0x4313:
-	case 0x4331:
-	case 43224:
-	case 43225:
-		break;
-	default:
-		pr_err("PMU switch/regulators init unknown for device "
-			"0x%04X\n", bus->chipinfo.id);
-	}
+	/* Add some delay; allow resources to come up and settle. */
+	mdelay(2);
 }
 
 /* Disable to allow reading SPROM. Don't know the adventages of enabling it. */
@@ -122,8 +91,11 @@
 		val |= BCMA_CHIPCTL_4331_EXTPA_EN;
 		if (bus->chipinfo.pkg == 9 || bus->chipinfo.pkg == 11)
 			val |= BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5;
+		else if (bus->chipinfo.rev > 0)
+			val |= BCMA_CHIPCTL_4331_EXTPA_EN2;
 	} else {
 		val &= ~BCMA_CHIPCTL_4331_EXTPA_EN;
+		val &= ~BCMA_CHIPCTL_4331_EXTPA_EN2;
 		val &= ~BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5;
 	}
 	bcma_cc_write32(cc, BCMA_CC_CHIPCTL, val);
@@ -134,26 +106,38 @@
 	struct bcma_bus *bus = cc->core->bus;
 
 	switch (bus->chipinfo.id) {
-	case 0x4313:
-		bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x7);
+	case BCMA_CHIP_ID_BCM4313:
+		/* enable 12 mA drive strenth for 4313 and set chipControl
+		   register bit 1 */
+		bcma_chipco_chipctl_maskset(cc, 0,
+					    ~BCMA_CCTRL_4313_12MA_LED_DRIVE,
+					    BCMA_CCTRL_4313_12MA_LED_DRIVE);
 		break;
-	case 0x4331:
-		/* BCM4331 workaround is SPROM-related, we put it in sprom.c */
+	case BCMA_CHIP_ID_BCM4331:
+	case BCMA_CHIP_ID_BCM43431:
+		/* Ext PA lines must be enabled for tx on BCM4331 */
+		bcma_chipco_bcm4331_ext_pa_lines_ctl(cc, true);
 		break;
-	case 43224:
+	case BCMA_CHIP_ID_BCM43224:
+	case BCMA_CHIP_ID_BCM43421:
+		/* enable 12 mA drive strenth for 43224 and set chipControl
+		   register bit 15 */
 		if (bus->chipinfo.rev == 0) {
-			pr_err("Workarounds for 43224 rev 0 not fully "
-				"implemented\n");
-			bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x00F000F0);
+			bcma_cc_maskset32(cc, BCMA_CC_CHIPCTL,
+					  ~BCMA_CCTRL_43224_GPIO_TOGGLE,
+					  BCMA_CCTRL_43224_GPIO_TOGGLE);
+			bcma_chipco_chipctl_maskset(cc, 0,
+						    ~BCMA_CCTRL_43224A0_12MA_LED_DRIVE,
+						    BCMA_CCTRL_43224A0_12MA_LED_DRIVE);
 		} else {
-			bcma_chipco_chipctl_maskset(cc, 0, ~0, 0xF0);
+			bcma_chipco_chipctl_maskset(cc, 0,
+						    ~BCMA_CCTRL_43224B0_12MA_LED_DRIVE,
+						    BCMA_CCTRL_43224B0_12MA_LED_DRIVE);
 		}
 		break;
-	case 43225:
-		break;
 	default:
-		pr_err("Workarounds unknown for device 0x%04X\n",
-			bus->chipinfo.id);
+		bcma_debug(bus, "Workarounds unknown or not needed for device 0x%04X\n",
+			   bus->chipinfo.id);
 	}
 }
 
@@ -164,8 +148,8 @@
 	pmucap = bcma_cc_read32(cc, BCMA_CC_PMU_CAP);
 	cc->pmu.rev = (pmucap & BCMA_CC_PMU_CAP_REVISION);
 
-	pr_debug("Found rev %u PMU (capabilities 0x%08X)\n", cc->pmu.rev,
-		 pmucap);
+	bcma_debug(cc->core->bus, "Found rev %u PMU (capabilities 0x%08X)\n",
+		   cc->pmu.rev, pmucap);
 
 	if (cc->pmu.rev == 1)
 		bcma_cc_mask32(cc, BCMA_CC_PMU_CTL,
@@ -174,12 +158,7 @@
 		bcma_cc_set32(cc, BCMA_CC_PMU_CTL,
 			     BCMA_CC_PMU_CTL_NOILPONW);
 
-	if (cc->core->id.id == 0x4329 && cc->core->id.rev == 2)
-		pr_err("Fix for 4329b0 bad LPOM state not implemented!\n");
-
-	bcma_pmu_pll_init(cc);
 	bcma_pmu_resources_init(cc);
-	bcma_pmu_swreg_init(cc);
 	bcma_pmu_workarounds(cc);
 }
 
@@ -188,23 +167,22 @@
 	struct bcma_bus *bus = cc->core->bus;
 
 	switch (bus->chipinfo.id) {
-	case 0x4716:
-	case 0x4748:
-	case 47162:
-	case 0x4313:
-	case 0x5357:
-	case 0x4749:
-	case 53572:
+	case BCMA_CHIP_ID_BCM4716:
+	case BCMA_CHIP_ID_BCM4748:
+	case BCMA_CHIP_ID_BCM47162:
+	case BCMA_CHIP_ID_BCM4313:
+	case BCMA_CHIP_ID_BCM5357:
+	case BCMA_CHIP_ID_BCM4749:
+	case BCMA_CHIP_ID_BCM53572:
 		/* always 20Mhz */
 		return 20000 * 1000;
-	case 0x5356:
-	case 0x5300:
+	case BCMA_CHIP_ID_BCM5356:
+	case BCMA_CHIP_ID_BCM4706:
 		/* always 25Mhz */
 		return 25000 * 1000;
 	default:
-		pr_warn("No ALP clock specified for %04X device, "
-			"pmu rev. %d, using default %d Hz\n",
-			bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_ALP_CLOCK);
+		bcma_warn(bus, "No ALP clock specified for %04X device, pmu rev. %d, using default %d Hz\n",
+			  bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_ALP_CLOCK);
 	}
 	return BCMA_CC_PMU_ALP_CLOCK;
 }
@@ -221,7 +199,8 @@
 
 	BUG_ON(!m || m > 4);
 
-	if (bus->chipinfo.id == 0x5357 || bus->chipinfo.id == 0x4749) {
+	if (bus->chipinfo.id == BCMA_CHIP_ID_BCM5357 ||
+	    bus->chipinfo.id == BCMA_CHIP_ID_BCM4749) {
 		/* Detect failure in clock setting */
 		tmp = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
 		if (tmp & 0x40000)
@@ -247,33 +226,62 @@
 	return (fc / div) * 1000000;
 }
 
+static u32 bcma_pmu_clock_bcm4706(struct bcma_drv_cc *cc, u32 pll0, u32 m)
+{
+	u32 tmp, ndiv, p1div, p2div;
+	u32 clock;
+
+	BUG_ON(!m || m > 4);
+
+	/* Get N, P1 and P2 dividers to determine CPU clock */
+	tmp = bcma_chipco_pll_read(cc, pll0 + BCMA_CC_PMU6_4706_PROCPLL_OFF);
+	ndiv = (tmp & BCMA_CC_PMU6_4706_PROC_NDIV_INT_MASK)
+		>> BCMA_CC_PMU6_4706_PROC_NDIV_INT_SHIFT;
+	p1div = (tmp & BCMA_CC_PMU6_4706_PROC_P1DIV_MASK)
+		>> BCMA_CC_PMU6_4706_PROC_P1DIV_SHIFT;
+	p2div = (tmp & BCMA_CC_PMU6_4706_PROC_P2DIV_MASK)
+		>> BCMA_CC_PMU6_4706_PROC_P2DIV_SHIFT;
+
+	tmp = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
+	if (tmp & BCMA_CC_CHIPST_4706_PKG_OPTION)
+		/* Low cost bonding: Fixed reference clock 25MHz and m = 4 */
+		clock = (25000000 / 4) * ndiv * p2div / p1div;
+	else
+		/* Fixed reference clock 25MHz and m = 2 */
+		clock = (25000000 / 2) * ndiv * p2div / p1div;
+
+	if (m == BCMA_CC_PMU5_MAINPLL_SSB)
+		clock = clock / 4;
+
+	return clock;
+}
+
 /* query bus clock frequency for PMU-enabled chipcommon */
 u32 bcma_pmu_get_clockcontrol(struct bcma_drv_cc *cc)
 {
 	struct bcma_bus *bus = cc->core->bus;
 
 	switch (bus->chipinfo.id) {
-	case 0x4716:
-	case 0x4748:
-	case 47162:
+	case BCMA_CHIP_ID_BCM4716:
+	case BCMA_CHIP_ID_BCM4748:
+	case BCMA_CHIP_ID_BCM47162:
 		return bcma_pmu_clock(cc, BCMA_CC_PMU4716_MAINPLL_PLL0,
 				      BCMA_CC_PMU5_MAINPLL_SSB);
-	case 0x5356:
+	case BCMA_CHIP_ID_BCM5356:
 		return bcma_pmu_clock(cc, BCMA_CC_PMU5356_MAINPLL_PLL0,
 				      BCMA_CC_PMU5_MAINPLL_SSB);
-	case 0x5357:
-	case 0x4749:
+	case BCMA_CHIP_ID_BCM5357:
+	case BCMA_CHIP_ID_BCM4749:
 		return bcma_pmu_clock(cc, BCMA_CC_PMU5357_MAINPLL_PLL0,
 				      BCMA_CC_PMU5_MAINPLL_SSB);
-	case 0x5300:
-		return bcma_pmu_clock(cc, BCMA_CC_PMU4706_MAINPLL_PLL0,
-				      BCMA_CC_PMU5_MAINPLL_SSB);
-	case 53572:
+	case BCMA_CHIP_ID_BCM4706:
+		return bcma_pmu_clock_bcm4706(cc, BCMA_CC_PMU4706_MAINPLL_PLL0,
+					      BCMA_CC_PMU5_MAINPLL_SSB);
+	case BCMA_CHIP_ID_BCM53572:
 		return 75000000;
 	default:
-		pr_warn("No backplane clock specified for %04X device, "
-			"pmu rev. %d, using default %d Hz\n",
-			bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_HT_CLOCK);
+		bcma_warn(bus, "No backplane clock specified for %04X device, pmu rev. %d, using default %d Hz\n",
+			  bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_HT_CLOCK);
 	}
 	return BCMA_CC_PMU_HT_CLOCK;
 }
@@ -283,17 +291,21 @@
 {
 	struct bcma_bus *bus = cc->core->bus;
 
-	if (bus->chipinfo.id == 53572)
+	if (bus->chipinfo.id == BCMA_CHIP_ID_BCM53572)
 		return 300000000;
 
 	if (cc->pmu.rev >= 5) {
 		u32 pll;
 		switch (bus->chipinfo.id) {
-		case 0x5356:
+		case BCMA_CHIP_ID_BCM4706:
+			return bcma_pmu_clock_bcm4706(cc,
+						BCMA_CC_PMU4706_MAINPLL_PLL0,
+						BCMA_CC_PMU5_MAINPLL_CPU);
+		case BCMA_CHIP_ID_BCM5356:
 			pll = BCMA_CC_PMU5356_MAINPLL_PLL0;
 			break;
-		case 0x5357:
-		case 0x4749:
+		case BCMA_CHIP_ID_BCM5357:
+		case BCMA_CHIP_ID_BCM4749:
 			pll = BCMA_CC_PMU5357_MAINPLL_PLL0;
 			break;
 		default:
@@ -301,10 +313,188 @@
 			break;
 		}
 
-		/* TODO: if (bus->chipinfo.id == 0x5300)
-		  return si_4706_pmu_clock(sih, osh, cc, PMU4706_MAINPLL_PLL0, PMU5_MAINPLL_CPU); */
 		return bcma_pmu_clock(cc, pll, BCMA_CC_PMU5_MAINPLL_CPU);
 	}
 
 	return bcma_pmu_get_clockcontrol(cc);
 }
+
+static void bcma_pmu_spuravoid_pll_write(struct bcma_drv_cc *cc, u32 offset,
+					 u32 value)
+{
+	bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset);
+	bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, value);
+}
+
+void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid)
+{
+	u32 tmp = 0;
+	u8 phypll_offset = 0;
+	u8 bcm5357_bcm43236_p1div[] = {0x1, 0x5, 0x5};
+	u8 bcm5357_bcm43236_ndiv[] = {0x30, 0xf6, 0xfc};
+	struct bcma_bus *bus = cc->core->bus;
+
+	switch (bus->chipinfo.id) {
+	case BCMA_CHIP_ID_BCM5357:
+	case BCMA_CHIP_ID_BCM4749:
+	case BCMA_CHIP_ID_BCM53572:
+		/* 5357[ab]0, 43236[ab]0, and 6362b0 */
+
+		/* BCM5357 needs to touch PLL1_PLLCTL[02],
+		   so offset PLL0_PLLCTL[02] by 6 */
+		phypll_offset = (bus->chipinfo.id == BCMA_CHIP_ID_BCM5357 ||
+		       bus->chipinfo.id == BCMA_CHIP_ID_BCM4749 ||
+		       bus->chipinfo.id == BCMA_CHIP_ID_BCM53572) ? 6 : 0;
+
+		/* RMW only the P1 divider */
+		bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR,
+				BCMA_CC_PMU_PLL_CTL0 + phypll_offset);
+		tmp = bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA);
+		tmp &= (~(BCMA_CC_PMU1_PLL0_PC0_P1DIV_MASK));
+		tmp |= (bcm5357_bcm43236_p1div[spuravoid] << BCMA_CC_PMU1_PLL0_PC0_P1DIV_SHIFT);
+		bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, tmp);
+
+		/* RMW only the int feedback divider */
+		bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR,
+				BCMA_CC_PMU_PLL_CTL2 + phypll_offset);
+		tmp = bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA);
+		tmp &= ~(BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_MASK);
+		tmp |= (bcm5357_bcm43236_ndiv[spuravoid]) << BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_SHIFT;
+		bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, tmp);
+
+		tmp = 1 << 10;
+		break;
+
+	case BCMA_CHIP_ID_BCM4331:
+	case BCMA_CHIP_ID_BCM43431:
+		if (spuravoid == 2) {
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
+						     0x11500014);
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
+						     0x0FC00a08);
+		} else if (spuravoid == 1) {
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
+						     0x11500014);
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
+						     0x0F600a08);
+		} else {
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
+						     0x11100014);
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
+						     0x03000a08);
+		}
+		tmp = 1 << 10;
+		break;
+
+	case BCMA_CHIP_ID_BCM43224:
+	case BCMA_CHIP_ID_BCM43225:
+	case BCMA_CHIP_ID_BCM43421:
+		if (spuravoid == 1) {
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
+						     0x11500010);
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1,
+						     0x000C0C06);
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
+						     0x0F600a08);
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3,
+						     0x00000000);
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4,
+						     0x2001E920);
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5,
+						     0x88888815);
+		} else {
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
+						     0x11100010);
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1,
+						     0x000c0c06);
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
+						     0x03000a08);
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3,
+						     0x00000000);
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4,
+						     0x200005c0);
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5,
+						     0x88888815);
+		}
+		tmp = 1 << 10;
+		break;
+
+	case BCMA_CHIP_ID_BCM4716:
+	case BCMA_CHIP_ID_BCM4748:
+	case BCMA_CHIP_ID_BCM47162:
+		if (spuravoid == 1) {
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
+						     0x11500060);
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1,
+						     0x080C0C06);
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
+						     0x0F600000);
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3,
+						     0x00000000);
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4,
+						     0x2001E924);
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5,
+						     0x88888815);
+		} else {
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
+						     0x11100060);
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1,
+						     0x080c0c06);
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
+						     0x03000000);
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3,
+						     0x00000000);
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4,
+						     0x200005c0);
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5,
+						     0x88888815);
+		}
+
+		tmp = 3 << 9;
+		break;
+
+	case BCMA_CHIP_ID_BCM43227:
+	case BCMA_CHIP_ID_BCM43228:
+	case BCMA_CHIP_ID_BCM43428:
+		/* LCNXN */
+		/* PLL Settings for spur avoidance on/off mode,
+		   no on2 support for 43228A0 */
+		if (spuravoid == 1) {
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
+						     0x01100014);
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1,
+						     0x040C0C06);
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
+						     0x03140A08);
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3,
+						     0x00333333);
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4,
+						     0x202C2820);
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5,
+						     0x88888815);
+		} else {
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL0,
+						     0x11100014);
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL1,
+						     0x040c0c06);
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL2,
+						     0x03000a08);
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL3,
+						     0x00000000);
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL4,
+						     0x200005c0);
+			bcma_pmu_spuravoid_pll_write(cc, BCMA_CC_PMU_PLL_CTL5,
+						     0x88888815);
+		}
+		tmp = 1 << 10;
+		break;
+	default:
+		bcma_err(bus, "Unknown spuravoidance settings for chip 0x%04X, not changing PLL\n",
+			 bus->chipinfo.id);
+		break;
+	}
+
+	tmp |= bcma_cc_read32(cc, BCMA_CC_PMU_CTL);
+	bcma_cc_write32(cc, BCMA_CC_PMU_CTL, tmp);
+}
+EXPORT_SYMBOL_GPL(bcma_pmu_spuravoid_pllupdate);
diff --git a/drivers/bcma/driver_gmac_cmn.c b/drivers/bcma/driver_gmac_cmn.c
new file mode 100644
index 0000000..834225f
--- /dev/null
+++ b/drivers/bcma/driver_gmac_cmn.c
@@ -0,0 +1,14 @@
+/*
+ * Broadcom specific AMBA
+ * GBIT MAC COMMON Core
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+#include "bcma_private.h"
+#include <linux/bcma/bcma.h>
+
+void __devinit bcma_core_gmac_cmn_init(struct bcma_drv_gmac_cmn *gc)
+{
+	mutex_init(&gc->phy_mutex);
+}
diff --git a/drivers/bcma/driver_mips.c b/drivers/bcma/driver_mips.c
index c3e9dff..4c4086b 100644
--- a/drivers/bcma/driver_mips.c
+++ b/drivers/bcma/driver_mips.c
@@ -22,15 +22,15 @@
 /* The 47162a0 hangs when reading MIPS DMP registers registers */
 static inline bool bcma_core_mips_bcm47162a0_quirk(struct bcma_device *dev)
 {
-	return dev->bus->chipinfo.id == 47162 && dev->bus->chipinfo.rev == 0 &&
-	       dev->id.id == BCMA_CORE_MIPS_74K;
+	return dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM47162 &&
+	       dev->bus->chipinfo.rev == 0 && dev->id.id == BCMA_CORE_MIPS_74K;
 }
 
 /* The 5357b0 hangs when reading USB20H DMP registers */
 static inline bool bcma_core_mips_bcm5357b0_quirk(struct bcma_device *dev)
 {
-	return (dev->bus->chipinfo.id == 0x5357 ||
-		dev->bus->chipinfo.id == 0x4749) &&
+	return (dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM5357 ||
+		dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM4749) &&
 	       dev->bus->chipinfo.pkg == 11 &&
 	       dev->id.id == BCMA_CORE_USB20_HOST;
 }
@@ -131,7 +131,7 @@
 			/* backplane irq line is in use, find out who uses
 			 * it and set user to irq 0
 			 */
-			list_for_each_entry_reverse(core, &bus->cores, list) {
+			list_for_each_entry(core, &bus->cores, list) {
 				if ((1 << bcma_core_mips_irqflag(core)) ==
 				    oldirqflag) {
 					bcma_core_mips_set_irq(core, 0);
@@ -143,8 +143,8 @@
 			     1 << irqflag);
 	}
 
-	pr_info("set_irq: core 0x%04x, irq %d => %d\n",
-		dev->id.id, oldirq + 2, irq + 2);
+	bcma_info(bus, "set_irq: core 0x%04x, irq %d => %d\n",
+		  dev->id.id, oldirq + 2, irq + 2);
 }
 
 static void bcma_core_mips_print_irq(struct bcma_device *dev, unsigned int irq)
@@ -161,7 +161,7 @@
 {
 	struct bcma_device *core;
 
-	list_for_each_entry_reverse(core, &bus->cores, list) {
+	list_for_each_entry(core, &bus->cores, list) {
 		bcma_core_mips_print_irq(core, bcma_core_mips_irq(core));
 	}
 }
@@ -173,7 +173,7 @@
 	if (bus->drv_cc.capabilities & BCMA_CC_CAP_PMU)
 		return bcma_pmu_get_clockcpu(&bus->drv_cc);
 
-	pr_err("No PMU available, need this to get the cpu clock\n");
+	bcma_err(bus, "No PMU available, need this to get the cpu clock\n");
 	return 0;
 }
 EXPORT_SYMBOL(bcma_cpu_clock);
@@ -185,10 +185,10 @@
 	switch (bus->drv_cc.capabilities & BCMA_CC_CAP_FLASHT) {
 	case BCMA_CC_FLASHT_STSER:
 	case BCMA_CC_FLASHT_ATSER:
-		pr_err("Serial flash not supported.\n");
+		bcma_err(bus, "Serial flash not supported.\n");
 		break;
 	case BCMA_CC_FLASHT_PARA:
-		pr_info("found parallel flash.\n");
+		bcma_info(bus, "found parallel flash.\n");
 		bus->drv_cc.pflash.window = 0x1c000000;
 		bus->drv_cc.pflash.window_size = 0x02000000;
 
@@ -199,7 +199,7 @@
 			bus->drv_cc.pflash.buswidth = 2;
 		break;
 	default:
-		pr_err("flash not supported.\n");
+		bcma_err(bus, "flash not supported.\n");
 	}
 }
 
@@ -209,13 +209,13 @@
 	struct bcma_device *core;
 	bus = mcore->core->bus;
 
-	pr_info("Initializing MIPS core...\n");
+	bcma_info(bus, "Initializing MIPS core...\n");
 
 	if (!mcore->setup_done)
 		mcore->assigned_irqs = 1;
 
 	/* Assign IRQs to all cores on the bus */
-	list_for_each_entry_reverse(core, &bus->cores, list) {
+	list_for_each_entry(core, &bus->cores, list) {
 		int mips_irq;
 		if (core->irq)
 			continue;
@@ -244,7 +244,7 @@
 			break;
 		}
 	}
-	pr_info("IRQ reconfiguration done\n");
+	bcma_info(bus, "IRQ reconfiguration done\n");
 	bcma_core_mips_dump_irq(bus);
 
 	if (mcore->setup_done)
diff --git a/drivers/bcma/driver_pci.c b/drivers/bcma/driver_pci.c
index 4fde625..c32ebd5 100644
--- a/drivers/bcma/driver_pci.c
+++ b/drivers/bcma/driver_pci.c
@@ -2,8 +2,9 @@
  * Broadcom specific AMBA
  * PCI Core
  *
- * Copyright 2005, Broadcom Corporation
+ * Copyright 2005, 2011, Broadcom Corporation
  * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
+ * Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de>
  *
  * Licensed under the GNU/GPL. See COPYING for details.
  */
@@ -16,40 +17,39 @@
  * R/W ops.
  **************************************************/
 
-static u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address)
+u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address)
 {
-	pcicore_write32(pc, 0x130, address);
-	pcicore_read32(pc, 0x130);
-	return pcicore_read32(pc, 0x134);
+	pcicore_write32(pc, BCMA_CORE_PCI_PCIEIND_ADDR, address);
+	pcicore_read32(pc, BCMA_CORE_PCI_PCIEIND_ADDR);
+	return pcicore_read32(pc, BCMA_CORE_PCI_PCIEIND_DATA);
 }
 
-#if 0
 static void bcma_pcie_write(struct bcma_drv_pci *pc, u32 address, u32 data)
 {
-	pcicore_write32(pc, 0x130, address);
-	pcicore_read32(pc, 0x130);
-	pcicore_write32(pc, 0x134, data);
+	pcicore_write32(pc, BCMA_CORE_PCI_PCIEIND_ADDR, address);
+	pcicore_read32(pc, BCMA_CORE_PCI_PCIEIND_ADDR);
+	pcicore_write32(pc, BCMA_CORE_PCI_PCIEIND_DATA, data);
 }
-#endif
 
 static void bcma_pcie_mdio_set_phy(struct bcma_drv_pci *pc, u8 phy)
 {
-	const u16 mdio_control = 0x128;
-	const u16 mdio_data = 0x12C;
 	u32 v;
 	int i;
 
-	v = (1 << 30); /* Start of Transaction */
-	v |= (1 << 28); /* Write Transaction */
-	v |= (1 << 17); /* Turnaround */
-	v |= (0x1F << 18);
+	v = BCMA_CORE_PCI_MDIODATA_START;
+	v |= BCMA_CORE_PCI_MDIODATA_WRITE;
+	v |= (BCMA_CORE_PCI_MDIODATA_DEV_ADDR <<
+	      BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF);
+	v |= (BCMA_CORE_PCI_MDIODATA_BLK_ADDR <<
+	      BCMA_CORE_PCI_MDIODATA_REGADDR_SHF);
+	v |= BCMA_CORE_PCI_MDIODATA_TA;
 	v |= (phy << 4);
-	pcicore_write32(pc, mdio_data, v);
+	pcicore_write32(pc, BCMA_CORE_PCI_MDIO_DATA, v);
 
 	udelay(10);
 	for (i = 0; i < 200; i++) {
-		v = pcicore_read32(pc, mdio_control);
-		if (v & 0x100 /* Trans complete */)
+		v = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_CONTROL);
+		if (v & BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE)
 			break;
 		msleep(1);
 	}
@@ -57,79 +57,84 @@
 
 static u16 bcma_pcie_mdio_read(struct bcma_drv_pci *pc, u8 device, u8 address)
 {
-	const u16 mdio_control = 0x128;
-	const u16 mdio_data = 0x12C;
 	int max_retries = 10;
 	u16 ret = 0;
 	u32 v;
 	int i;
 
-	v = 0x80; /* Enable Preamble Sequence */
-	v |= 0x2; /* MDIO Clock Divisor */
-	pcicore_write32(pc, mdio_control, v);
+	/* enable mdio access to SERDES */
+	v = BCMA_CORE_PCI_MDIOCTL_PREAM_EN;
+	v |= BCMA_CORE_PCI_MDIOCTL_DIVISOR_VAL;
+	pcicore_write32(pc, BCMA_CORE_PCI_MDIO_CONTROL, v);
 
 	if (pc->core->id.rev >= 10) {
 		max_retries = 200;
 		bcma_pcie_mdio_set_phy(pc, device);
+		v = (BCMA_CORE_PCI_MDIODATA_DEV_ADDR <<
+		     BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF);
+		v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF);
+	} else {
+		v = (device << BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF_OLD);
+		v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF_OLD);
 	}
 
-	v = (1 << 30); /* Start of Transaction */
-	v |= (1 << 29); /* Read Transaction */
-	v |= (1 << 17); /* Turnaround */
-	if (pc->core->id.rev < 10)
-		v |= (u32)device << 22;
-	v |= (u32)address << 18;
-	pcicore_write32(pc, mdio_data, v);
+	v = BCMA_CORE_PCI_MDIODATA_START;
+	v |= BCMA_CORE_PCI_MDIODATA_READ;
+	v |= BCMA_CORE_PCI_MDIODATA_TA;
+
+	pcicore_write32(pc, BCMA_CORE_PCI_MDIO_DATA, v);
 	/* Wait for the device to complete the transaction */
 	udelay(10);
 	for (i = 0; i < max_retries; i++) {
-		v = pcicore_read32(pc, mdio_control);
-		if (v & 0x100 /* Trans complete */) {
+		v = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_CONTROL);
+		if (v & BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE) {
 			udelay(10);
-			ret = pcicore_read32(pc, mdio_data);
+			ret = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_DATA);
 			break;
 		}
 		msleep(1);
 	}
-	pcicore_write32(pc, mdio_control, 0);
+	pcicore_write32(pc, BCMA_CORE_PCI_MDIO_CONTROL, 0);
 	return ret;
 }
 
 static void bcma_pcie_mdio_write(struct bcma_drv_pci *pc, u8 device,
 				u8 address, u16 data)
 {
-	const u16 mdio_control = 0x128;
-	const u16 mdio_data = 0x12C;
 	int max_retries = 10;
 	u32 v;
 	int i;
 
-	v = 0x80; /* Enable Preamble Sequence */
-	v |= 0x2; /* MDIO Clock Divisor */
-	pcicore_write32(pc, mdio_control, v);
+	/* enable mdio access to SERDES */
+	v = BCMA_CORE_PCI_MDIOCTL_PREAM_EN;
+	v |= BCMA_CORE_PCI_MDIOCTL_DIVISOR_VAL;
+	pcicore_write32(pc, BCMA_CORE_PCI_MDIO_CONTROL, v);
 
 	if (pc->core->id.rev >= 10) {
 		max_retries = 200;
 		bcma_pcie_mdio_set_phy(pc, device);
+		v = (BCMA_CORE_PCI_MDIODATA_DEV_ADDR <<
+		     BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF);
+		v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF);
+	} else {
+		v = (device << BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF_OLD);
+		v |= (address << BCMA_CORE_PCI_MDIODATA_REGADDR_SHF_OLD);
 	}
 
-	v = (1 << 30); /* Start of Transaction */
-	v |= (1 << 28); /* Write Transaction */
-	v |= (1 << 17); /* Turnaround */
-	if (pc->core->id.rev < 10)
-		v |= (u32)device << 22;
-	v |= (u32)address << 18;
+	v = BCMA_CORE_PCI_MDIODATA_START;
+	v |= BCMA_CORE_PCI_MDIODATA_WRITE;
+	v |= BCMA_CORE_PCI_MDIODATA_TA;
 	v |= data;
-	pcicore_write32(pc, mdio_data, v);
+	pcicore_write32(pc, BCMA_CORE_PCI_MDIO_DATA, v);
 	/* Wait for the device to complete the transaction */
 	udelay(10);
 	for (i = 0; i < max_retries; i++) {
-		v = pcicore_read32(pc, mdio_control);
-		if (v & 0x100 /* Trans complete */)
+		v = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_CONTROL);
+		if (v & BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE)
 			break;
 		msleep(1);
 	}
-	pcicore_write32(pc, mdio_control, 0);
+	pcicore_write32(pc, BCMA_CORE_PCI_MDIO_CONTROL, 0);
 }
 
 /**************************************************
@@ -138,88 +143,108 @@
 
 static u8 bcma_pcicore_polarity_workaround(struct bcma_drv_pci *pc)
 {
-	return (bcma_pcie_read(pc, 0x204) & 0x10) ? 0xC0 : 0x80;
+	u32 tmp;
+
+	tmp = bcma_pcie_read(pc, BCMA_CORE_PCI_PLP_STATUSREG);
+	if (tmp & BCMA_CORE_PCI_PLP_POLARITYINV_STAT)
+		return BCMA_CORE_PCI_SERDES_RX_CTRL_FORCE |
+		       BCMA_CORE_PCI_SERDES_RX_CTRL_POLARITY;
+	else
+		return BCMA_CORE_PCI_SERDES_RX_CTRL_FORCE;
 }
 
 static void bcma_pcicore_serdes_workaround(struct bcma_drv_pci *pc)
 {
-	const u8 serdes_pll_device = 0x1D;
-	const u8 serdes_rx_device = 0x1F;
 	u16 tmp;
 
-	bcma_pcie_mdio_write(pc, serdes_rx_device, 1 /* Control */,
-			      bcma_pcicore_polarity_workaround(pc));
-	tmp = bcma_pcie_mdio_read(pc, serdes_pll_device, 1 /* Control */);
-	if (tmp & 0x4000)
-		bcma_pcie_mdio_write(pc, serdes_pll_device, 1, tmp & ~0x4000);
+	bcma_pcie_mdio_write(pc, BCMA_CORE_PCI_MDIODATA_DEV_RX,
+	                     BCMA_CORE_PCI_SERDES_RX_CTRL,
+			     bcma_pcicore_polarity_workaround(pc));
+	tmp = bcma_pcie_mdio_read(pc, BCMA_CORE_PCI_MDIODATA_DEV_PLL,
+	                          BCMA_CORE_PCI_SERDES_PLL_CTRL);
+	if (tmp & BCMA_CORE_PCI_PLL_CTRL_FREQDET_EN)
+		bcma_pcie_mdio_write(pc, BCMA_CORE_PCI_MDIODATA_DEV_PLL,
+		                     BCMA_CORE_PCI_SERDES_PLL_CTRL,
+		                     tmp & ~BCMA_CORE_PCI_PLL_CTRL_FREQDET_EN);
+}
+
+static void bcma_core_pci_fixcfg(struct bcma_drv_pci *pc)
+{
+	struct bcma_device *core = pc->core;
+	u16 val16, core_index;
+	uint regoff;
+
+	regoff = BCMA_CORE_PCI_SPROM(BCMA_CORE_PCI_SPROM_PI_OFFSET);
+	core_index = (u16)core->core_index;
+
+	val16 = pcicore_read16(pc, regoff);
+	if (((val16 & BCMA_CORE_PCI_SPROM_PI_MASK) >> BCMA_CORE_PCI_SPROM_PI_SHIFT)
+	     != core_index) {
+		val16 = (core_index << BCMA_CORE_PCI_SPROM_PI_SHIFT) |
+			(val16 & ~BCMA_CORE_PCI_SPROM_PI_MASK);
+		pcicore_write16(pc, regoff, val16);
+	}
+}
+
+/* Fix MISC config to allow coming out of L2/L3-Ready state w/o PRST */
+/* Needs to happen when coming out of 'standby'/'hibernate' */
+static void bcma_core_pci_config_fixup(struct bcma_drv_pci *pc)
+{
+	u16 val16;
+	uint regoff;
+
+	regoff = BCMA_CORE_PCI_SPROM(BCMA_CORE_PCI_SPROM_MISC_CONFIG);
+
+	val16 = pcicore_read16(pc, regoff);
+
+	if (!(val16 & BCMA_CORE_PCI_SPROM_L23READY_EXIT_NOPERST)) {
+		val16 |= BCMA_CORE_PCI_SPROM_L23READY_EXIT_NOPERST;
+		pcicore_write16(pc, regoff, val16);
+	}
 }
 
 /**************************************************
  * Init.
  **************************************************/
 
-static void bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc)
+static void __devinit bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc)
 {
+	bcma_core_pci_fixcfg(pc);
 	bcma_pcicore_serdes_workaround(pc);
+	bcma_core_pci_config_fixup(pc);
 }
 
-static bool bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc)
-{
-	struct bcma_bus *bus = pc->core->bus;
-	u16 chipid_top;
-
-	chipid_top = (bus->chipinfo.id & 0xFF00);
-	if (chipid_top != 0x4700 &&
-	    chipid_top != 0x5300)
-		return false;
-
-#ifdef CONFIG_SSB_DRIVER_PCICORE
-	if (bus->sprom.boardflags_lo & SSB_BFL_NOPCI)
-		return false;
-#endif /* CONFIG_SSB_DRIVER_PCICORE */
-
-#if 0
-	/* TODO: on BCMA we use address from EROM instead of magic formula */
-	u32 tmp;
-	return !mips_busprobe32(tmp, (bus->mmio +
-		(pc->core->core_index * BCMA_CORE_SIZE)));
-#endif
-
-	return true;
-}
-
-void bcma_core_pci_init(struct bcma_drv_pci *pc)
+void __devinit bcma_core_pci_init(struct bcma_drv_pci *pc)
 {
 	if (pc->setup_done)
 		return;
 
-	if (bcma_core_pci_is_in_hostmode(pc)) {
 #ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
+	pc->hostmode = bcma_core_pci_is_in_hostmode(pc);
+	if (pc->hostmode)
 		bcma_core_pci_hostmode_init(pc);
-#else
-		pr_err("Driver compiled without support for hostmode PCI\n");
 #endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */
-	} else {
-		bcma_core_pci_clientmode_init(pc);
-	}
 
-	pc->setup_done = true;
+	if (!pc->hostmode)
+		bcma_core_pci_clientmode_init(pc);
 }
 
 int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core,
 			  bool enable)
 {
-	struct pci_dev *pdev = pc->core->bus->host_pci;
+	struct pci_dev *pdev;
 	u32 coremask, tmp;
 	int err = 0;
 
-	if (core->bus->hosttype != BCMA_HOSTTYPE_PCI) {
+	if (!pc || core->bus->hosttype != BCMA_HOSTTYPE_PCI) {
 		/* This bcma device is not on a PCI host-bus. So the IRQs are
 		 * not routed through the PCI core.
 		 * So we must not enable routing through the PCI core. */
 		goto out;
 	}
 
+	pdev = pc->core->bus->host_pci;
+
 	err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp);
 	if (err)
 		goto out;
@@ -236,3 +261,17 @@
 	return err;
 }
 EXPORT_SYMBOL_GPL(bcma_core_pci_irq_ctl);
+
+void bcma_core_pci_extend_L1timer(struct bcma_drv_pci *pc, bool extend)
+{
+	u32 w;
+
+	w = bcma_pcie_read(pc, BCMA_CORE_PCI_DLLP_PMTHRESHREG);
+	if (extend)
+		w |= BCMA_CORE_PCI_ASPMTIMER_EXTEND;
+	else
+		w &= ~BCMA_CORE_PCI_ASPMTIMER_EXTEND;
+	bcma_pcie_write(pc, BCMA_CORE_PCI_DLLP_PMTHRESHREG, w);
+	bcma_pcie_read(pc, BCMA_CORE_PCI_DLLP_PMTHRESHREG);
+}
+EXPORT_SYMBOL_GPL(bcma_core_pci_extend_L1timer);
diff --git a/drivers/bcma/driver_pci_host.c b/drivers/bcma/driver_pci_host.c
index eb332b7..cbae2c2 100644
--- a/drivers/bcma/driver_pci_host.c
+++ b/drivers/bcma/driver_pci_host.c
@@ -2,13 +2,592 @@
  * Broadcom specific AMBA
  * PCI Core in hostmode
  *
+ * Copyright 2005 - 2011, Broadcom Corporation
+ * Copyright 2006, 2007, Michael Buesch <m@bues.ch>
+ * Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de>
+ *
  * Licensed under the GNU/GPL. See COPYING for details.
  */
 
 #include "bcma_private.h"
+#include <linux/pci.h>
+#include <linux/export.h>
 #include <linux/bcma/bcma.h>
+#include <asm/paccess.h>
 
-void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
+/* Probe a 32bit value on the bus and catch bus exceptions.
+ * Returns nonzero on a bus exception.
+ * This is MIPS specific */
+#define mips_busprobe32(val, addr)	get_dbe((val), ((u32 *)(addr)))
+
+/* Assume one-hot slot wiring */
+#define BCMA_PCI_SLOT_MAX	16
+#define	PCI_CONFIG_SPACE_SIZE	256
+
+bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc)
 {
-	pr_err("No support for PCI core in hostmode yet\n");
+	struct bcma_bus *bus = pc->core->bus;
+	u16 chipid_top;
+	u32 tmp;
+
+	chipid_top = (bus->chipinfo.id & 0xFF00);
+	if (chipid_top != 0x4700 &&
+	    chipid_top != 0x5300)
+		return false;
+
+	if (bus->sprom.boardflags_lo & BCMA_CORE_PCI_BFL_NOPCI) {
+		bcma_info(bus, "This PCI core is disabled and not working\n");
+		return false;
+	}
+
+	bcma_core_enable(pc->core, 0);
+
+	return !mips_busprobe32(tmp, pc->core->io_addr);
 }
+
+static u32 bcma_pcie_read_config(struct bcma_drv_pci *pc, u32 address)
+{
+	pcicore_write32(pc, BCMA_CORE_PCI_CONFIG_ADDR, address);
+	pcicore_read32(pc, BCMA_CORE_PCI_CONFIG_ADDR);
+	return pcicore_read32(pc, BCMA_CORE_PCI_CONFIG_DATA);
+}
+
+static void bcma_pcie_write_config(struct bcma_drv_pci *pc, u32 address,
+				   u32 data)
+{
+	pcicore_write32(pc, BCMA_CORE_PCI_CONFIG_ADDR, address);
+	pcicore_read32(pc, BCMA_CORE_PCI_CONFIG_ADDR);
+	pcicore_write32(pc, BCMA_CORE_PCI_CONFIG_DATA, data);
+}
+
+static u32 bcma_get_cfgspace_addr(struct bcma_drv_pci *pc, unsigned int dev,
+			     unsigned int func, unsigned int off)
+{
+	u32 addr = 0;
+
+	/* Issue config commands only when the data link is up (atleast
+	 * one external pcie device is present).
+	 */
+	if (dev >= 2 || !(bcma_pcie_read(pc, BCMA_CORE_PCI_DLLP_LSREG)
+			  & BCMA_CORE_PCI_DLLP_LSREG_LINKUP))
+		goto out;
+
+	/* Type 0 transaction */
+	/* Slide the PCI window to the appropriate slot */
+	pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI1, BCMA_CORE_PCI_SBTOPCI_CFG0);
+	/* Calculate the address */
+	addr = pc->host_controller->host_cfg_addr;
+	addr |= (dev << BCMA_CORE_PCI_CFG_SLOT_SHIFT);
+	addr |= (func << BCMA_CORE_PCI_CFG_FUN_SHIFT);
+	addr |= (off & ~3);
+
+out:
+	return addr;
+}
+
+static int bcma_extpci_read_config(struct bcma_drv_pci *pc, unsigned int dev,
+				  unsigned int func, unsigned int off,
+				  void *buf, int len)
+{
+	int err = -EINVAL;
+	u32 addr, val;
+	void __iomem *mmio = 0;
+
+	WARN_ON(!pc->hostmode);
+	if (unlikely(len != 1 && len != 2 && len != 4))
+		goto out;
+	if (dev == 0) {
+		/* we support only two functions on device 0 */
+		if (func > 1)
+			return -EINVAL;
+
+		/* accesses to config registers with offsets >= 256
+		 * requires indirect access.
+		 */
+		if (off >= PCI_CONFIG_SPACE_SIZE) {
+			addr = (func << 12);
+			addr |= (off & 0x0FFF);
+			val = bcma_pcie_read_config(pc, addr);
+		} else {
+			addr = BCMA_CORE_PCI_PCICFG0;
+			addr |= (func << 8);
+			addr |= (off & 0xfc);
+			val = pcicore_read32(pc, addr);
+		}
+	} else {
+		addr = bcma_get_cfgspace_addr(pc, dev, func, off);
+		if (unlikely(!addr))
+			goto out;
+		err = -ENOMEM;
+		mmio = ioremap_nocache(addr, sizeof(val));
+		if (!mmio)
+			goto out;
+
+		if (mips_busprobe32(val, mmio)) {
+			val = 0xffffffff;
+			goto unmap;
+		}
+
+		val = readl(mmio);
+	}
+	val >>= (8 * (off & 3));
+
+	switch (len) {
+	case 1:
+		*((u8 *)buf) = (u8)val;
+		break;
+	case 2:
+		*((u16 *)buf) = (u16)val;
+		break;
+	case 4:
+		*((u32 *)buf) = (u32)val;
+		break;
+	}
+	err = 0;
+unmap:
+	if (mmio)
+		iounmap(mmio);
+out:
+	return err;
+}
+
+static int bcma_extpci_write_config(struct bcma_drv_pci *pc, unsigned int dev,
+				   unsigned int func, unsigned int off,
+				   const void *buf, int len)
+{
+	int err = -EINVAL;
+	u32 addr = 0, val = 0;
+	void __iomem *mmio = 0;
+	u16 chipid = pc->core->bus->chipinfo.id;
+
+	WARN_ON(!pc->hostmode);
+	if (unlikely(len != 1 && len != 2 && len != 4))
+		goto out;
+	if (dev == 0) {
+		/* accesses to config registers with offsets >= 256
+		 * requires indirect access.
+		 */
+		if (off < PCI_CONFIG_SPACE_SIZE) {
+			addr = pc->core->addr + BCMA_CORE_PCI_PCICFG0;
+			addr |= (func << 8);
+			addr |= (off & 0xfc);
+			mmio = ioremap_nocache(addr, sizeof(val));
+			if (!mmio)
+				goto out;
+		}
+	} else {
+		addr = bcma_get_cfgspace_addr(pc, dev, func, off);
+		if (unlikely(!addr))
+			goto out;
+		err = -ENOMEM;
+		mmio = ioremap_nocache(addr, sizeof(val));
+		if (!mmio)
+			goto out;
+
+		if (mips_busprobe32(val, mmio)) {
+			val = 0xffffffff;
+			goto unmap;
+		}
+	}
+
+	switch (len) {
+	case 1:
+		val = readl(mmio);
+		val &= ~(0xFF << (8 * (off & 3)));
+		val |= *((const u8 *)buf) << (8 * (off & 3));
+		break;
+	case 2:
+		val = readl(mmio);
+		val &= ~(0xFFFF << (8 * (off & 3)));
+		val |= *((const u16 *)buf) << (8 * (off & 3));
+		break;
+	case 4:
+		val = *((const u32 *)buf);
+		break;
+	}
+	if (dev == 0 && !addr) {
+		/* accesses to config registers with offsets >= 256
+		 * requires indirect access.
+		 */
+		addr = (func << 12);
+		addr |= (off & 0x0FFF);
+		bcma_pcie_write_config(pc, addr, val);
+	} else {
+		writel(val, mmio);
+
+		if (chipid == BCMA_CHIP_ID_BCM4716 ||
+		    chipid == BCMA_CHIP_ID_BCM4748)
+			readl(mmio);
+	}
+
+	err = 0;
+unmap:
+	if (mmio)
+		iounmap(mmio);
+out:
+	return err;
+}
+
+static int bcma_core_pci_hostmode_read_config(struct pci_bus *bus,
+					      unsigned int devfn,
+					      int reg, int size, u32 *val)
+{
+	unsigned long flags;
+	int err;
+	struct bcma_drv_pci *pc;
+	struct bcma_drv_pci_host *pc_host;
+
+	pc_host = container_of(bus->ops, struct bcma_drv_pci_host, pci_ops);
+	pc = pc_host->pdev;
+
+	spin_lock_irqsave(&pc_host->cfgspace_lock, flags);
+	err = bcma_extpci_read_config(pc, PCI_SLOT(devfn),
+				     PCI_FUNC(devfn), reg, val, size);
+	spin_unlock_irqrestore(&pc_host->cfgspace_lock, flags);
+
+	return err ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
+}
+
+static int bcma_core_pci_hostmode_write_config(struct pci_bus *bus,
+					       unsigned int devfn,
+					       int reg, int size, u32 val)
+{
+	unsigned long flags;
+	int err;
+	struct bcma_drv_pci *pc;
+	struct bcma_drv_pci_host *pc_host;
+
+	pc_host = container_of(bus->ops, struct bcma_drv_pci_host, pci_ops);
+	pc = pc_host->pdev;
+
+	spin_lock_irqsave(&pc_host->cfgspace_lock, flags);
+	err = bcma_extpci_write_config(pc, PCI_SLOT(devfn),
+				      PCI_FUNC(devfn), reg, &val, size);
+	spin_unlock_irqrestore(&pc_host->cfgspace_lock, flags);
+
+	return err ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
+}
+
+/* return cap_offset if requested capability exists in the PCI config space */
+static u8 __devinit bcma_find_pci_capability(struct bcma_drv_pci *pc,
+					     unsigned int dev,
+					     unsigned int func, u8 req_cap_id,
+					     unsigned char *buf, u32 *buflen)
+{
+	u8 cap_id;
+	u8 cap_ptr = 0;
+	u32 bufsize;
+	u8 byte_val;
+
+	/* check for Header type 0 */
+	bcma_extpci_read_config(pc, dev, func, PCI_HEADER_TYPE, &byte_val,
+				sizeof(u8));
+	if ((byte_val & 0x7f) != PCI_HEADER_TYPE_NORMAL)
+		return cap_ptr;
+
+	/* check if the capability pointer field exists */
+	bcma_extpci_read_config(pc, dev, func, PCI_STATUS, &byte_val,
+				sizeof(u8));
+	if (!(byte_val & PCI_STATUS_CAP_LIST))
+		return cap_ptr;
+
+	/* check if the capability pointer is 0x00 */
+	bcma_extpci_read_config(pc, dev, func, PCI_CAPABILITY_LIST, &cap_ptr,
+				sizeof(u8));
+	if (cap_ptr == 0x00)
+		return cap_ptr;
+
+	/* loop thr'u the capability list and see if the requested capabilty
+	 * exists */
+	bcma_extpci_read_config(pc, dev, func, cap_ptr, &cap_id, sizeof(u8));
+	while (cap_id != req_cap_id) {
+		bcma_extpci_read_config(pc, dev, func, cap_ptr + 1, &cap_ptr,
+					sizeof(u8));
+		if (cap_ptr == 0x00)
+			return cap_ptr;
+		bcma_extpci_read_config(pc, dev, func, cap_ptr, &cap_id,
+					sizeof(u8));
+	}
+
+	/* found the caller requested capability */
+	if ((buf != NULL) && (buflen != NULL)) {
+		u8 cap_data;
+
+		bufsize = *buflen;
+		if (!bufsize)
+			return cap_ptr;
+
+		*buflen = 0;
+
+		/* copy the cpability data excluding cap ID and next ptr */
+		cap_data = cap_ptr + 2;
+		if ((bufsize + cap_data)  > PCI_CONFIG_SPACE_SIZE)
+			bufsize = PCI_CONFIG_SPACE_SIZE - cap_data;
+		*buflen = bufsize;
+		while (bufsize--) {
+			bcma_extpci_read_config(pc, dev, func, cap_data, buf,
+						sizeof(u8));
+			cap_data++;
+			buf++;
+		}
+	}
+
+	return cap_ptr;
+}
+
+/* If the root port is capable of returning Config Request
+ * Retry Status (CRS) Completion Status to software then
+ * enable the feature.
+ */
+static void __devinit bcma_core_pci_enable_crs(struct bcma_drv_pci *pc)
+{
+	struct bcma_bus *bus = pc->core->bus;
+	u8 cap_ptr, root_ctrl, root_cap, dev;
+	u16 val16;
+	int i;
+
+	cap_ptr = bcma_find_pci_capability(pc, 0, 0, PCI_CAP_ID_EXP, NULL,
+					   NULL);
+	root_cap = cap_ptr + PCI_EXP_RTCAP;
+	bcma_extpci_read_config(pc, 0, 0, root_cap, &val16, sizeof(u16));
+	if (val16 & BCMA_CORE_PCI_RC_CRS_VISIBILITY) {
+		/* Enable CRS software visibility */
+		root_ctrl = cap_ptr + PCI_EXP_RTCTL;
+		val16 = PCI_EXP_RTCTL_CRSSVE;
+		bcma_extpci_read_config(pc, 0, 0, root_ctrl, &val16,
+					sizeof(u16));
+
+		/* Initiate a configuration request to read the vendor id
+		 * field of the device function's config space header after
+		 * 100 ms wait time from the end of Reset. If the device is
+		 * not done with its internal initialization, it must at
+		 * least return a completion TLP, with a completion status
+		 * of "Configuration Request Retry Status (CRS)". The root
+		 * complex must complete the request to the host by returning
+		 * a read-data value of 0001h for the Vendor ID field and
+		 * all 1s for any additional bytes included in the request.
+		 * Poll using the config reads for max wait time of 1 sec or
+		 * until we receive the successful completion status. Repeat
+		 * the procedure for all the devices.
+		 */
+		for (dev = 1; dev < BCMA_PCI_SLOT_MAX; dev++) {
+			for (i = 0; i < 100000; i++) {
+				bcma_extpci_read_config(pc, dev, 0,
+							PCI_VENDOR_ID, &val16,
+							sizeof(val16));
+				if (val16 != 0x1)
+					break;
+				udelay(10);
+			}
+			if (val16 == 0x1)
+				bcma_err(bus, "PCI: Broken device in slot %d\n",
+					 dev);
+		}
+	}
+}
+
+void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
+{
+	struct bcma_bus *bus = pc->core->bus;
+	struct bcma_drv_pci_host *pc_host;
+	u32 tmp;
+	u32 pci_membase_1G;
+	unsigned long io_map_base;
+
+	bcma_info(bus, "PCIEcore in host mode found\n");
+
+	pc_host = kzalloc(sizeof(*pc_host), GFP_KERNEL);
+	if (!pc_host)  {
+		bcma_err(bus, "can not allocate memory");
+		return;
+	}
+
+	pc->host_controller = pc_host;
+	pc_host->pci_controller.io_resource = &pc_host->io_resource;
+	pc_host->pci_controller.mem_resource = &pc_host->mem_resource;
+	pc_host->pci_controller.pci_ops = &pc_host->pci_ops;
+	pc_host->pdev = pc;
+
+	pci_membase_1G = BCMA_SOC_PCI_DMA;
+	pc_host->host_cfg_addr = BCMA_SOC_PCI_CFG;
+
+	pc_host->pci_ops.read = bcma_core_pci_hostmode_read_config;
+	pc_host->pci_ops.write = bcma_core_pci_hostmode_write_config;
+
+	pc_host->mem_resource.name = "BCMA PCIcore external memory",
+	pc_host->mem_resource.start = BCMA_SOC_PCI_DMA;
+	pc_host->mem_resource.end = BCMA_SOC_PCI_DMA + BCMA_SOC_PCI_DMA_SZ - 1;
+	pc_host->mem_resource.flags = IORESOURCE_MEM | IORESOURCE_PCI_FIXED;
+
+	pc_host->io_resource.name = "BCMA PCIcore external I/O",
+	pc_host->io_resource.start = 0x100;
+	pc_host->io_resource.end = 0x7FF;
+	pc_host->io_resource.flags = IORESOURCE_IO | IORESOURCE_PCI_FIXED;
+
+	/* Reset RC */
+	udelay(3000);
+	pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST_OE);
+	udelay(1000);
+	pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST |
+			BCMA_CORE_PCI_CTL_RST_OE);
+
+	/* 64 MB I/O access window. On 4716, use
+	 * sbtopcie0 to access the device registers. We
+	 * can't use address match 2 (1 GB window) region
+	 * as mips can't generate 64-bit address on the
+	 * backplane.
+	 */
+	if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4716 ||
+	    bus->chipinfo.id == BCMA_CHIP_ID_BCM4748) {
+		pc_host->mem_resource.start = BCMA_SOC_PCI_MEM;
+		pc_host->mem_resource.end = BCMA_SOC_PCI_MEM +
+					    BCMA_SOC_PCI_MEM_SZ - 1;
+		pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0,
+				BCMA_CORE_PCI_SBTOPCI_MEM | BCMA_SOC_PCI_MEM);
+	} else if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) {
+		tmp = BCMA_CORE_PCI_SBTOPCI_MEM;
+		tmp |= BCMA_CORE_PCI_SBTOPCI_PREF;
+		tmp |= BCMA_CORE_PCI_SBTOPCI_BURST;
+		if (pc->core->core_unit == 0) {
+			pc_host->mem_resource.start = BCMA_SOC_PCI_MEM;
+			pc_host->mem_resource.end = BCMA_SOC_PCI_MEM +
+						    BCMA_SOC_PCI_MEM_SZ - 1;
+			pci_membase_1G = BCMA_SOC_PCIE_DMA_H32;
+			pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0,
+					tmp | BCMA_SOC_PCI_MEM);
+		} else if (pc->core->core_unit == 1) {
+			pc_host->mem_resource.start = BCMA_SOC_PCI1_MEM;
+			pc_host->mem_resource.end = BCMA_SOC_PCI1_MEM +
+						    BCMA_SOC_PCI_MEM_SZ - 1;
+			pci_membase_1G = BCMA_SOC_PCIE1_DMA_H32;
+			pc_host->host_cfg_addr = BCMA_SOC_PCI1_CFG;
+			pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0,
+					tmp | BCMA_SOC_PCI1_MEM);
+		}
+	} else
+		pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0,
+				BCMA_CORE_PCI_SBTOPCI_IO);
+
+	/* 64 MB configuration access window */
+	pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI1, BCMA_CORE_PCI_SBTOPCI_CFG0);
+
+	/* 1 GB memory access window */
+	pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI2,
+			BCMA_CORE_PCI_SBTOPCI_MEM | pci_membase_1G);
+
+
+	/* As per PCI Express Base Spec 1.1 we need to wait for
+	 * at least 100 ms from the end of a reset (cold/warm/hot)
+	 * before issuing configuration requests to PCI Express
+	 * devices.
+	 */
+	udelay(100000);
+
+	bcma_core_pci_enable_crs(pc);
+
+	/* Enable PCI bridge BAR0 memory & master access */
+	tmp = PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+	bcma_extpci_write_config(pc, 0, 0, PCI_COMMAND, &tmp, sizeof(tmp));
+
+	/* Enable PCI interrupts */
+	pcicore_write32(pc, BCMA_CORE_PCI_IMASK, BCMA_CORE_PCI_IMASK_INTA);
+
+	/* Ok, ready to run, register it to the system.
+	 * The following needs change, if we want to port hostmode
+	 * to non-MIPS platform. */
+	io_map_base = (unsigned long)ioremap_nocache(pc_host->mem_resource.start,
+						     resource_size(&pc_host->mem_resource));
+	pc_host->pci_controller.io_map_base = io_map_base;
+	set_io_port_base(pc_host->pci_controller.io_map_base);
+	/* Give some time to the PCI controller to configure itself with the new
+	 * values. Not waiting at this point causes crashes of the machine. */
+	mdelay(10);
+	register_pci_controller(&pc_host->pci_controller);
+	return;
+}
+
+/* Early PCI fixup for a device on the PCI-core bridge. */
+static void bcma_core_pci_fixup_pcibridge(struct pci_dev *dev)
+{
+	if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) {
+		/* This is not a device on the PCI-core bridge. */
+		return;
+	}
+	if (PCI_SLOT(dev->devfn) != 0)
+		return;
+
+	pr_info("PCI: Fixing up bridge %s\n", pci_name(dev));
+
+	/* Enable PCI bridge bus mastering and memory space */
+	pci_set_master(dev);
+	if (pcibios_enable_device(dev, ~0) < 0) {
+		pr_err("PCI: BCMA bridge enable failed\n");
+		return;
+	}
+
+	/* Enable PCI bridge BAR1 prefetch and burst */
+	pci_write_config_dword(dev, BCMA_PCI_BAR1_CONTROL, 3);
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, bcma_core_pci_fixup_pcibridge);
+
+/* Early PCI fixup for all PCI-cores to set the correct memory address. */
+static void bcma_core_pci_fixup_addresses(struct pci_dev *dev)
+{
+	struct resource *res;
+	int pos;
+
+	if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) {
+		/* This is not a device on the PCI-core bridge. */
+		return;
+	}
+	if (PCI_SLOT(dev->devfn) == 0)
+		return;
+
+	pr_info("PCI: Fixing up addresses %s\n", pci_name(dev));
+
+	for (pos = 0; pos < 6; pos++) {
+		res = &dev->resource[pos];
+		if (res->flags & (IORESOURCE_IO | IORESOURCE_MEM))
+			pci_assign_resource(dev, pos);
+	}
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, bcma_core_pci_fixup_addresses);
+
+/* This function is called when doing a pci_enable_device().
+ * We must first check if the device is a device on the PCI-core bridge. */
+int bcma_core_pci_plat_dev_init(struct pci_dev *dev)
+{
+	struct bcma_drv_pci_host *pc_host;
+
+	if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) {
+		/* This is not a device on the PCI-core bridge. */
+		return -ENODEV;
+	}
+	pc_host = container_of(dev->bus->ops, struct bcma_drv_pci_host,
+			       pci_ops);
+
+	pr_info("PCI: Fixing up device %s\n", pci_name(dev));
+
+	/* Fix up interrupt lines */
+	dev->irq = bcma_core_mips_irq(pc_host->pdev->core) + 2;
+	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+
+	return 0;
+}
+EXPORT_SYMBOL(bcma_core_pci_plat_dev_init);
+
+/* PCI device IRQ mapping. */
+int bcma_core_pci_pcibios_map_irq(const struct pci_dev *dev)
+{
+	struct bcma_drv_pci_host *pc_host;
+
+	if (dev->bus->ops->read != bcma_core_pci_hostmode_read_config) {
+		/* This is not a device on the PCI-core bridge. */
+		return -ENODEV;
+	}
+
+	pc_host = container_of(dev->bus->ops, struct bcma_drv_pci_host,
+			       pci_ops);
+	return bcma_core_mips_irq(pc_host->pdev->core) + 2;
+}
+EXPORT_SYMBOL(bcma_core_pci_pcibios_map_irq);
diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c
index f59244e..11b32d2 100644
--- a/drivers/bcma/host_pci.c
+++ b/drivers/bcma/host_pci.c
@@ -18,7 +18,7 @@
 	pci_write_config_dword(core->bus->host_pci, BCMA_PCI_BAR0_WIN2,
 			       core->wrap);
 	core->bus->mapped_core = core;
-	pr_debug("Switched to core: 0x%X\n", core->id.id);
+	bcma_debug(core->bus, "Switched to core: 0x%X\n", core->id.id);
 }
 
 /* Provides access to the requested core. Returns base offset that has to be
@@ -154,8 +154,8 @@
 	.awrite32	= bcma_host_pci_awrite32,
 };
 
-static int bcma_host_pci_probe(struct pci_dev *dev,
-			     const struct pci_device_id *id)
+static int __devinit bcma_host_pci_probe(struct pci_dev *dev,
+					 const struct pci_device_id *id)
 {
 	struct bcma_bus *bus;
 	int err = -ENOMEM;
@@ -188,7 +188,7 @@
 
 	/* SSB needed additional powering up, do we have any AMBA PCI cards? */
 	if (!pci_is_pcie(dev))
-		pr_err("PCI card detected, report problems.\n");
+		bcma_err(bus, "PCI card detected, report problems.\n");
 
 	/* Map MMIO */
 	err = -ENOMEM;
@@ -201,6 +201,9 @@
 	bus->hosttype = BCMA_HOSTTYPE_PCI;
 	bus->ops = &bcma_host_pci_ops;
 
+	bus->boardinfo.vendor = bus->host_pci->subsystem_vendor;
+	bus->boardinfo.type = bus->host_pci->subsystem_device;
+
 	/* Register */
 	err = bcma_bus_register(bus);
 	if (err)
@@ -222,7 +225,7 @@
 	return err;
 }
 
-static void bcma_host_pci_remove(struct pci_dev *dev)
+static void __devexit bcma_host_pci_remove(struct pci_dev *dev)
 {
 	struct bcma_bus *bus = pci_get_drvdata(dev);
 
@@ -265,6 +268,7 @@
 
 static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43224) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) },
@@ -277,7 +281,7 @@
 	.name = "bcma-pci-bridge",
 	.id_table = bcma_pci_bridge_tbl,
 	.probe = bcma_host_pci_probe,
-	.remove = bcma_host_pci_remove,
+	.remove = __devexit_p(bcma_host_pci_remove),
 	.driver.pm = BCMA_PM_OPS,
 };
 
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c
index ec31f7d..758af9c 100644
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -13,6 +13,12 @@
 MODULE_DESCRIPTION("Broadcom's specific AMBA driver");
 MODULE_LICENSE("GPL");
 
+/* contains the number the next bus should get. */
+static unsigned int bcma_bus_next_num = 0;
+
+/* bcma_buses_mutex locks the bcma_bus_next_num */
+static DEFINE_MUTEX(bcma_buses_mutex);
+
 static int bcma_bus_match(struct device *dev, struct device_driver *drv);
 static int bcma_device_probe(struct device *dev);
 static int bcma_device_remove(struct device *dev);
@@ -55,7 +61,14 @@
 	.dev_attrs	= bcma_device_attrs,
 };
 
-static struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)
+static u16 bcma_cc_core_id(struct bcma_bus *bus)
+{
+	if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706)
+		return BCMA_CORE_4706_CHIPCOMMON;
+	return BCMA_CORE_CHIPCOMMON;
+}
+
+struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)
 {
 	struct bcma_device *core;
 
@@ -65,6 +78,7 @@
 	}
 	return NULL;
 }
+EXPORT_SYMBOL_GPL(bcma_find_core);
 
 static void bcma_release_core_dev(struct device *dev)
 {
@@ -84,16 +98,18 @@
 	list_for_each_entry(core, &bus->cores, list) {
 		/* We support that cores ourself */
 		switch (core->id.id) {
+		case BCMA_CORE_4706_CHIPCOMMON:
 		case BCMA_CORE_CHIPCOMMON:
 		case BCMA_CORE_PCI:
 		case BCMA_CORE_PCIE:
 		case BCMA_CORE_MIPS_74K:
+		case BCMA_CORE_4706_MAC_GBIT_COMMON:
 			continue;
 		}
 
 		core->dev.release = bcma_release_core_dev;
 		core->dev.bus = &bcma_bus_type;
-		dev_set_name(&core->dev, "bcma%d:%d", 0/*bus->num*/, dev_id);
+		dev_set_name(&core->dev, "bcma%d:%d", bus->num, dev_id);
 
 		switch (bus->hosttype) {
 		case BCMA_HOSTTYPE_PCI:
@@ -111,8 +127,9 @@
 
 		err = device_register(&core->dev);
 		if (err) {
-			pr_err("Could not register dev for core 0x%03X\n",
-			       core->id.id);
+			bcma_err(bus,
+				 "Could not register dev for core 0x%03X\n",
+				 core->id.id);
 			continue;
 		}
 		core->dev_registered = true;
@@ -132,20 +149,24 @@
 	}
 }
 
-int bcma_bus_register(struct bcma_bus *bus)
+int __devinit bcma_bus_register(struct bcma_bus *bus)
 {
 	int err;
 	struct bcma_device *core;
 
+	mutex_lock(&bcma_buses_mutex);
+	bus->num = bcma_bus_next_num++;
+	mutex_unlock(&bcma_buses_mutex);
+
 	/* Scan for devices (cores) */
 	err = bcma_bus_scan(bus);
 	if (err) {
-		pr_err("Failed to scan: %d\n", err);
+		bcma_err(bus, "Failed to scan: %d\n", err);
 		return -1;
 	}
 
 	/* Init CC core */
-	core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON);
+	core = bcma_find_core(bus, bcma_cc_core_id(bus));
 	if (core) {
 		bus->drv_cc.core = core;
 		bcma_core_chipcommon_init(&bus->drv_cc);
@@ -165,17 +186,24 @@
 		bcma_core_pci_init(&bus->drv_pci);
 	}
 
+	/* Init GBIT MAC COMMON core */
+	core = bcma_find_core(bus, BCMA_CORE_4706_MAC_GBIT_COMMON);
+	if (core) {
+		bus->drv_gmac_cmn.core = core;
+		bcma_core_gmac_cmn_init(&bus->drv_gmac_cmn);
+	}
+
 	/* Try to get SPROM */
 	err = bcma_sprom_get(bus);
 	if (err == -ENOENT) {
-		pr_err("No SPROM available\n");
+		bcma_err(bus, "No SPROM available\n");
 	} else if (err)
-		pr_err("Failed to get SPROM: %d\n", err);
+		bcma_err(bus, "Failed to get SPROM: %d\n", err);
 
 	/* Register found cores */
 	bcma_register_cores(bus);
 
-	pr_info("Bus registered\n");
+	bcma_info(bus, "Bus registered\n");
 
 	return 0;
 }
@@ -196,14 +224,14 @@
 	bcma_init_bus(bus);
 
 	match.manuf = BCMA_MANUF_BCM;
-	match.id = BCMA_CORE_CHIPCOMMON;
+	match.id = bcma_cc_core_id(bus);
 	match.class = BCMA_CL_SIM;
 	match.rev = BCMA_ANY_REV;
 
 	/* Scan for chip common core */
 	err = bcma_bus_scan_early(bus, &match, core_cc);
 	if (err) {
-		pr_err("Failed to scan for common core: %d\n", err);
+		bcma_err(bus, "Failed to scan for common core: %d\n", err);
 		return -1;
 	}
 
@@ -215,12 +243,12 @@
 	/* Scan for mips core */
 	err = bcma_bus_scan_early(bus, &match, core_mips);
 	if (err) {
-		pr_err("Failed to scan for mips core: %d\n", err);
+		bcma_err(bus, "Failed to scan for mips core: %d\n", err);
 		return -1;
 	}
 
 	/* Init CC core */
-	core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON);
+	core = bcma_find_core(bus, bcma_cc_core_id(bus));
 	if (core) {
 		bus->drv_cc.core = core;
 		bcma_core_chipcommon_init(&bus->drv_cc);
@@ -233,7 +261,7 @@
 		bcma_core_mips_init(&bus->drv_mips);
 	}
 
-	pr_info("Early bus registered\n");
+	bcma_info(bus, "Early bus registered\n");
 
 	return 0;
 }
@@ -259,8 +287,7 @@
 	struct bcma_device *core;
 
 	/* Init CC core */
-	core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON);
-	if (core) {
+	if (bus->drv_cc.core) {
 		bus->drv_cc.setup_done = false;
 		bcma_core_chipcommon_init(&bus->drv_cc);
 	}
diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c
index 3a2f672..8d0b571 100644
--- a/drivers/bcma/scan.c
+++ b/drivers/bcma/scan.c
@@ -19,15 +19,27 @@
 	u16 id;
 	const char *name;
 };
-struct bcma_device_id_name bcma_device_names[] = {
+
+static const struct bcma_device_id_name bcma_arm_device_names[] = {
+	{ BCMA_CORE_4706_MAC_GBIT_COMMON, "BCM4706 GBit MAC Common" },
+	{ BCMA_CORE_ARM_1176, "ARM 1176" },
+	{ BCMA_CORE_ARM_7TDMI, "ARM 7TDMI" },
+	{ BCMA_CORE_ARM_CM3, "ARM CM3" },
+};
+
+static const struct bcma_device_id_name bcma_bcm_device_names[] = {
 	{ BCMA_CORE_OOB_ROUTER, "OOB Router" },
+	{ BCMA_CORE_4706_CHIPCOMMON, "BCM4706 ChipCommon" },
+	{ BCMA_CORE_4706_SOC_RAM, "BCM4706 SOC RAM" },
+	{ BCMA_CORE_4706_MAC_GBIT, "BCM4706 GBit MAC" },
+	{ BCMA_CORE_AMEMC, "AMEMC (DDR)" },
+	{ BCMA_CORE_ALTA, "ALTA (I2S)" },
 	{ BCMA_CORE_INVALID, "Invalid" },
 	{ BCMA_CORE_CHIPCOMMON, "ChipCommon" },
 	{ BCMA_CORE_ILINE20, "ILine 20" },
 	{ BCMA_CORE_SRAM, "SRAM" },
 	{ BCMA_CORE_SDRAM, "SDRAM" },
 	{ BCMA_CORE_PCI, "PCI" },
-	{ BCMA_CORE_MIPS, "MIPS" },
 	{ BCMA_CORE_ETHERNET, "Fast Ethernet" },
 	{ BCMA_CORE_V90, "V90" },
 	{ BCMA_CORE_USB11_HOSTDEV, "USB 1.1 Hostdev" },
@@ -44,7 +56,6 @@
 	{ BCMA_CORE_PHY_A, "PHY A" },
 	{ BCMA_CORE_PHY_B, "PHY B" },
 	{ BCMA_CORE_PHY_G, "PHY G" },
-	{ BCMA_CORE_MIPS_3302, "MIPS 3302" },
 	{ BCMA_CORE_USB11_HOST, "USB 1.1 Host" },
 	{ BCMA_CORE_USB11_DEV, "USB 1.1 Device" },
 	{ BCMA_CORE_USB20_HOST, "USB 2.0 Host" },
@@ -58,15 +69,11 @@
 	{ BCMA_CORE_PHY_N, "PHY N" },
 	{ BCMA_CORE_SRAM_CTL, "SRAM Controller" },
 	{ BCMA_CORE_MINI_MACPHY, "Mini MACPHY" },
-	{ BCMA_CORE_ARM_1176, "ARM 1176" },
-	{ BCMA_CORE_ARM_7TDMI, "ARM 7TDMI" },
 	{ BCMA_CORE_PHY_LP, "PHY LP" },
 	{ BCMA_CORE_PMU, "PMU" },
 	{ BCMA_CORE_PHY_SSN, "PHY SSN" },
 	{ BCMA_CORE_SDIO_DEV, "SDIO Device" },
-	{ BCMA_CORE_ARM_CM3, "ARM CM3" },
 	{ BCMA_CORE_PHY_HT, "PHY HT" },
-	{ BCMA_CORE_MIPS_74K, "MIPS 74K" },
 	{ BCMA_CORE_MAC_GBIT, "GBit MAC" },
 	{ BCMA_CORE_DDR12_MEM_CTL, "DDR1/DDR2 Memory Controller" },
 	{ BCMA_CORE_PCIE_RC, "PCIe Root Complex" },
@@ -79,16 +86,41 @@
 	{ BCMA_CORE_SHIM, "SHIM" },
 	{ BCMA_CORE_DEFAULT, "Default" },
 };
-const char *bcma_device_name(struct bcma_device_id *id)
-{
-	int i;
 
-	if (id->manuf == BCMA_MANUF_BCM) {
-		for (i = 0; i < ARRAY_SIZE(bcma_device_names); i++) {
-			if (bcma_device_names[i].id == id->id)
-				return bcma_device_names[i].name;
-		}
+static const struct bcma_device_id_name bcma_mips_device_names[] = {
+	{ BCMA_CORE_MIPS, "MIPS" },
+	{ BCMA_CORE_MIPS_3302, "MIPS 3302" },
+	{ BCMA_CORE_MIPS_74K, "MIPS 74K" },
+};
+
+static const char *bcma_device_name(const struct bcma_device_id *id)
+{
+	const struct bcma_device_id_name *names;
+	int size, i;
+
+	/* search manufacturer specific names */
+	switch (id->manuf) {
+	case BCMA_MANUF_ARM:
+		names = bcma_arm_device_names;
+		size = ARRAY_SIZE(bcma_arm_device_names);
+		break;
+	case BCMA_MANUF_BCM:
+		names = bcma_bcm_device_names;
+		size = ARRAY_SIZE(bcma_bcm_device_names);
+		break;
+	case BCMA_MANUF_MIPS:
+		names = bcma_mips_device_names;
+		size = ARRAY_SIZE(bcma_mips_device_names);
+		break;
+	default:
+		return "UNKNOWN";
 	}
+
+	for (i = 0; i < size; i++) {
+		if (names[i].id == id->id)
+			return names[i].name;
+	}
+
 	return "UNKNOWN";
 }
 
@@ -212,6 +244,17 @@
 	return NULL;
 }
 
+static struct bcma_device *bcma_find_core_reverse(struct bcma_bus *bus, u16 coreid)
+{
+	struct bcma_device *core;
+
+	list_for_each_entry_reverse(core, &bus->cores, list) {
+		if (core->id.id == coreid)
+			return core;
+	}
+	return NULL;
+}
+
 static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
 			      struct bcma_device_id *match, int core_num,
 			      struct bcma_device *core)
@@ -252,11 +295,15 @@
 
 	/* check if component is a core at all */
 	if (wrappers[0] + wrappers[1] == 0) {
-		/* we could save addrl of the router
-		if (cid == BCMA_CORE_OOB_ROUTER)
-		 */
-		bcma_erom_skip_component(bus, eromptr);
-		return -ENXIO;
+		/* Some specific cores don't need wrappers */
+		switch (core->id.id) {
+		case BCMA_CORE_4706_MAC_GBIT_COMMON:
+		/* Not used yet: case BCMA_CORE_OOB_ROUTER: */
+			break;
+		default:
+			bcma_erom_skip_component(bus, eromptr);
+			return -ENXIO;
+		}
 	}
 
 	if (bcma_erom_is_bridge(bus, eromptr)) {
@@ -286,6 +333,23 @@
 			return -EILSEQ;
 	}
 
+	/* First Slave Address Descriptor should be port 0:
+	 * the main register space for the core
+	 */
+	tmp = bcma_erom_get_addr_desc(bus, eromptr, SCAN_ADDR_TYPE_SLAVE, 0);
+	if (tmp <= 0) {
+		/* Try again to see if it is a bridge */
+		tmp = bcma_erom_get_addr_desc(bus, eromptr,
+					      SCAN_ADDR_TYPE_BRIDGE, 0);
+		if (tmp <= 0) {
+			return -EILSEQ;
+		} else {
+			bcma_info(bus, "Bridge found\n");
+			return -ENXIO;
+		}
+	}
+	core->addr = tmp;
+
 	/* get & parse slave ports */
 	for (i = 0; i < ports[1]; i++) {
 		for (j = 0; ; j++) {
@@ -298,7 +362,7 @@
 				break;
 			} else {
 				if (i == 0 && j == 0)
-					core->addr = tmp;
+					core->addr1 = tmp;
 			}
 		}
 	}
@@ -353,6 +417,7 @@
 void bcma_init_bus(struct bcma_bus *bus)
 {
 	s32 tmp;
+	struct bcma_chipinfo *chipinfo = &(bus->chipinfo);
 
 	if (bus->init_done)
 		return;
@@ -363,9 +428,12 @@
 	bcma_scan_switch_core(bus, BCMA_ADDR_BASE);
 
 	tmp = bcma_scan_read32(bus, 0, BCMA_CC_ID);
-	bus->chipinfo.id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT;
-	bus->chipinfo.rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT;
-	bus->chipinfo.pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT;
+	chipinfo->id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT;
+	chipinfo->rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT;
+	chipinfo->pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT;
+	bcma_info(bus, "Found chip with id 0x%04X, rev 0x%02X and package 0x%02X\n",
+		  chipinfo->id, chipinfo->rev, chipinfo->pkg);
+
 	bus->init_done = true;
 }
 
@@ -392,9 +460,12 @@
 	bcma_scan_switch_core(bus, erombase);
 
 	while (eromptr < eromend) {
+		struct bcma_device *other_core;
 		struct bcma_device *core = kzalloc(sizeof(*core), GFP_KERNEL);
-		if (!core)
-			return -ENOMEM;
+		if (!core) {
+			err = -ENOMEM;
+			goto out;
+		}
 		INIT_LIST_HEAD(&core->list);
 		core->bus = bus;
 
@@ -409,25 +480,28 @@
 			} else if (err == -ESPIPE) {
 				break;
 			}
-			return err;
+			goto out;
 		}
 
 		core->core_index = core_num++;
 		bus->nr_cores++;
+		other_core = bcma_find_core_reverse(bus, core->id.id);
+		core->core_unit = (other_core == NULL) ? 0 : other_core->core_unit + 1;
 
-		pr_info("Core %d found: %s "
-			"(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n",
-			core->core_index, bcma_device_name(&core->id),
-			core->id.manuf, core->id.id, core->id.rev,
-			core->id.class);
+		bcma_info(bus, "Core %d found: %s (manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n",
+			  core->core_index, bcma_device_name(&core->id),
+			  core->id.manuf, core->id.id, core->id.rev,
+			  core->id.class);
 
-		list_add(&core->list, &bus->cores);
+		list_add_tail(&core->list, &bus->cores);
 	}
 
+	err = 0;
+out:
 	if (bus->hosttype == BCMA_HOSTTYPE_SOC)
 		iounmap(eromptr);
 
-	return 0;
+	return err;
 }
 
 int __init bcma_bus_scan_early(struct bcma_bus *bus,
@@ -467,21 +541,21 @@
 		else if (err == -ESPIPE)
 			break;
 		else if (err < 0)
-			return err;
+			goto out;
 
 		core->core_index = core_num++;
 		bus->nr_cores++;
-		pr_info("Core %d found: %s "
-			"(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n",
-			core->core_index, bcma_device_name(&core->id),
-			core->id.manuf, core->id.id, core->id.rev,
-			core->id.class);
+		bcma_info(bus, "Core %d found: %s (manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n",
+			  core->core_index, bcma_device_name(&core->id),
+			  core->id.manuf, core->id.id, core->id.rev,
+			  core->id.class);
 
-		list_add(&core->list, &bus->cores);
+		list_add_tail(&core->list, &bus->cores);
 		err = 0;
 		break;
 	}
 
+out:
 	if (bus->hosttype == BCMA_HOSTTYPE_SOC)
 		iounmap(eromptr);
 
diff --git a/drivers/bcma/scan.h b/drivers/bcma/scan.h
index 113e6a6..30eb475 100644
--- a/drivers/bcma/scan.h
+++ b/drivers/bcma/scan.h
@@ -27,7 +27,7 @@
 #define SCAN_CIB_NMW		0x0007C000
 #define SCAN_CIB_NMW_SHIFT	14
 #define SCAN_CIB_NSW		0x00F80000
-#define SCAN_CIB_NSW_SHIFT	17
+#define SCAN_CIB_NSW_SHIFT	19
 #define SCAN_CIB_REV		0xFF000000
 #define SCAN_CIB_REV_SHIFT	24
 
diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c
index 6f230fb..26823d9 100644
--- a/drivers/bcma/sprom.c
+++ b/drivers/bcma/sprom.c
@@ -2,6 +2,8 @@
  * Broadcom specific AMBA
  * SPROM reading
  *
+ * Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de>
+ *
  * Licensed under the GNU/GPL. See COPYING for details.
  */
 
@@ -14,7 +16,57 @@
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
 
-#define SPOFF(offset)	((offset) / sizeof(u16))
+static int(*get_fallback_sprom)(struct bcma_bus *dev, struct ssb_sprom *out);
+
+/**
+ * bcma_arch_register_fallback_sprom - Registers a method providing a
+ * fallback SPROM if no SPROM is found.
+ *
+ * @sprom_callback: The callback function.
+ *
+ * With this function the architecture implementation may register a
+ * callback handler which fills the SPROM data structure. The fallback is
+ * used for PCI based BCMA devices, where no valid SPROM can be found
+ * in the shadow registers and to provide the SPROM for SoCs where BCMA is
+ * to controll the system bus.
+ *
+ * This function is useful for weird architectures that have a half-assed
+ * BCMA device hardwired to their PCI bus.
+ *
+ * This function is available for architecture code, only. So it is not
+ * exported.
+ */
+int bcma_arch_register_fallback_sprom(int (*sprom_callback)(struct bcma_bus *bus,
+				     struct ssb_sprom *out))
+{
+	if (get_fallback_sprom)
+		return -EEXIST;
+	get_fallback_sprom = sprom_callback;
+
+	return 0;
+}
+
+static int bcma_fill_sprom_with_fallback(struct bcma_bus *bus,
+					 struct ssb_sprom *out)
+{
+	int err;
+
+	if (!get_fallback_sprom) {
+		err = -ENOENT;
+		goto fail;
+	}
+
+	err = get_fallback_sprom(bus, out);
+	if (err)
+		goto fail;
+
+	bcma_debug(bus, "Using SPROM revision %d provided by platform.\n",
+		   bus->sprom.revision);
+	return 0;
+fail:
+	bcma_warn(bus, "Using fallback SPROM failed (err %d)\n", err);
+	return err;
+}
 
 /**************************************************
  * R/W ops.
@@ -124,10 +176,37 @@
  * SPROM extraction.
  **************************************************/
 
+#define SPOFF(offset)	((offset) / sizeof(u16))
+
+#define SPEX(_field, _offset, _mask, _shift)	\
+	bus->sprom._field = ((sprom[SPOFF(_offset)] & (_mask)) >> (_shift))
+
+#define SPEX32(_field, _offset, _mask, _shift)	\
+	bus->sprom._field = ((((u32)sprom[SPOFF((_offset)+2)] << 16 | \
+				sprom[SPOFF(_offset)]) & (_mask)) >> (_shift))
+
+#define SPEX_ARRAY8(_field, _offset, _mask, _shift)	\
+	do {	\
+		SPEX(_field[0], _offset +  0, _mask, _shift);	\
+		SPEX(_field[1], _offset +  2, _mask, _shift);	\
+		SPEX(_field[2], _offset +  4, _mask, _shift);	\
+		SPEX(_field[3], _offset +  6, _mask, _shift);	\
+		SPEX(_field[4], _offset +  8, _mask, _shift);	\
+		SPEX(_field[5], _offset + 10, _mask, _shift);	\
+		SPEX(_field[6], _offset + 12, _mask, _shift);	\
+		SPEX(_field[7], _offset + 14, _mask, _shift);	\
+	} while (0)
+
 static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
 {
-	u16 v;
+	u16 v, o;
 	int i;
+	u16 pwr_info_offset[] = {
+		SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1,
+		SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3
+	};
+	BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) !=
+			ARRAY_SIZE(bus->sprom.core_pwr_info));
 
 	bus->sprom.revision = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] &
 		SSB_SPROM_REVISION_REV;
@@ -137,102 +216,378 @@
 		*(((__be16 *)bus->sprom.il0mac) + i) = cpu_to_be16(v);
 	}
 
-	bus->sprom.board_rev = sprom[SPOFF(SSB_SPROM8_BOARDREV)];
+	SPEX(board_rev, SSB_SPROM8_BOARDREV, ~0, 0);
 
-	bus->sprom.txpid2g[0] = (sprom[SPOFF(SSB_SPROM4_TXPID2G01)] &
-	     SSB_SPROM4_TXPID2G0) >> SSB_SPROM4_TXPID2G0_SHIFT;
-	bus->sprom.txpid2g[1] = (sprom[SPOFF(SSB_SPROM4_TXPID2G01)] &
-	     SSB_SPROM4_TXPID2G1) >> SSB_SPROM4_TXPID2G1_SHIFT;
-	bus->sprom.txpid2g[2] = (sprom[SPOFF(SSB_SPROM4_TXPID2G23)] &
-	     SSB_SPROM4_TXPID2G2) >> SSB_SPROM4_TXPID2G2_SHIFT;
-	bus->sprom.txpid2g[3] = (sprom[SPOFF(SSB_SPROM4_TXPID2G23)] &
-	     SSB_SPROM4_TXPID2G3) >> SSB_SPROM4_TXPID2G3_SHIFT;
+	SPEX(txpid2g[0], SSB_SPROM4_TXPID2G01, SSB_SPROM4_TXPID2G0,
+	     SSB_SPROM4_TXPID2G0_SHIFT);
+	SPEX(txpid2g[1], SSB_SPROM4_TXPID2G01, SSB_SPROM4_TXPID2G1,
+	     SSB_SPROM4_TXPID2G1_SHIFT);
+	SPEX(txpid2g[2], SSB_SPROM4_TXPID2G23, SSB_SPROM4_TXPID2G2,
+	     SSB_SPROM4_TXPID2G2_SHIFT);
+	SPEX(txpid2g[3], SSB_SPROM4_TXPID2G23, SSB_SPROM4_TXPID2G3,
+	     SSB_SPROM4_TXPID2G3_SHIFT);
 
-	bus->sprom.txpid5gl[0] = (sprom[SPOFF(SSB_SPROM4_TXPID5GL01)] &
-	     SSB_SPROM4_TXPID5GL0) >> SSB_SPROM4_TXPID5GL0_SHIFT;
-	bus->sprom.txpid5gl[1] = (sprom[SPOFF(SSB_SPROM4_TXPID5GL01)] &
-	     SSB_SPROM4_TXPID5GL1) >> SSB_SPROM4_TXPID5GL1_SHIFT;
-	bus->sprom.txpid5gl[2] = (sprom[SPOFF(SSB_SPROM4_TXPID5GL23)] &
-	     SSB_SPROM4_TXPID5GL2) >> SSB_SPROM4_TXPID5GL2_SHIFT;
-	bus->sprom.txpid5gl[3] = (sprom[SPOFF(SSB_SPROM4_TXPID5GL23)] &
-	     SSB_SPROM4_TXPID5GL3) >> SSB_SPROM4_TXPID5GL3_SHIFT;
+	SPEX(txpid5gl[0], SSB_SPROM4_TXPID5GL01, SSB_SPROM4_TXPID5GL0,
+	     SSB_SPROM4_TXPID5GL0_SHIFT);
+	SPEX(txpid5gl[1], SSB_SPROM4_TXPID5GL01, SSB_SPROM4_TXPID5GL1,
+	     SSB_SPROM4_TXPID5GL1_SHIFT);
+	SPEX(txpid5gl[2], SSB_SPROM4_TXPID5GL23, SSB_SPROM4_TXPID5GL2,
+	     SSB_SPROM4_TXPID5GL2_SHIFT);
+	SPEX(txpid5gl[3], SSB_SPROM4_TXPID5GL23, SSB_SPROM4_TXPID5GL3,
+	     SSB_SPROM4_TXPID5GL3_SHIFT);
 
-	bus->sprom.txpid5g[0] = (sprom[SPOFF(SSB_SPROM4_TXPID5G01)] &
-	     SSB_SPROM4_TXPID5G0) >> SSB_SPROM4_TXPID5G0_SHIFT;
-	bus->sprom.txpid5g[1] = (sprom[SPOFF(SSB_SPROM4_TXPID5G01)] &
-	     SSB_SPROM4_TXPID5G1) >> SSB_SPROM4_TXPID5G1_SHIFT;
-	bus->sprom.txpid5g[2] = (sprom[SPOFF(SSB_SPROM4_TXPID5G23)] &
-	     SSB_SPROM4_TXPID5G2) >> SSB_SPROM4_TXPID5G2_SHIFT;
-	bus->sprom.txpid5g[3] = (sprom[SPOFF(SSB_SPROM4_TXPID5G23)] &
-	     SSB_SPROM4_TXPID5G3) >> SSB_SPROM4_TXPID5G3_SHIFT;
+	SPEX(txpid5g[0], SSB_SPROM4_TXPID5G01, SSB_SPROM4_TXPID5G0,
+	     SSB_SPROM4_TXPID5G0_SHIFT);
+	SPEX(txpid5g[1], SSB_SPROM4_TXPID5G01, SSB_SPROM4_TXPID5G1,
+	     SSB_SPROM4_TXPID5G1_SHIFT);
+	SPEX(txpid5g[2], SSB_SPROM4_TXPID5G23, SSB_SPROM4_TXPID5G2,
+	     SSB_SPROM4_TXPID5G2_SHIFT);
+	SPEX(txpid5g[3], SSB_SPROM4_TXPID5G23, SSB_SPROM4_TXPID5G3,
+	     SSB_SPROM4_TXPID5G3_SHIFT);
 
-	bus->sprom.txpid5gh[0] = (sprom[SPOFF(SSB_SPROM4_TXPID5GH01)] &
-	     SSB_SPROM4_TXPID5GH0) >> SSB_SPROM4_TXPID5GH0_SHIFT;
-	bus->sprom.txpid5gh[1] = (sprom[SPOFF(SSB_SPROM4_TXPID5GH01)] &
-	     SSB_SPROM4_TXPID5GH1) >> SSB_SPROM4_TXPID5GH1_SHIFT;
-	bus->sprom.txpid5gh[2] = (sprom[SPOFF(SSB_SPROM4_TXPID5GH23)] &
-	     SSB_SPROM4_TXPID5GH2) >> SSB_SPROM4_TXPID5GH2_SHIFT;
-	bus->sprom.txpid5gh[3] = (sprom[SPOFF(SSB_SPROM4_TXPID5GH23)] &
-	     SSB_SPROM4_TXPID5GH3) >> SSB_SPROM4_TXPID5GH3_SHIFT;
+	SPEX(txpid5gh[0], SSB_SPROM4_TXPID5GH01, SSB_SPROM4_TXPID5GH0,
+	     SSB_SPROM4_TXPID5GH0_SHIFT);
+	SPEX(txpid5gh[1], SSB_SPROM4_TXPID5GH01, SSB_SPROM4_TXPID5GH1,
+	     SSB_SPROM4_TXPID5GH1_SHIFT);
+	SPEX(txpid5gh[2], SSB_SPROM4_TXPID5GH23, SSB_SPROM4_TXPID5GH2,
+	     SSB_SPROM4_TXPID5GH2_SHIFT);
+	SPEX(txpid5gh[3], SSB_SPROM4_TXPID5GH23, SSB_SPROM4_TXPID5GH3,
+	     SSB_SPROM4_TXPID5GH3_SHIFT);
 
-	bus->sprom.boardflags_lo = sprom[SPOFF(SSB_SPROM8_BFLLO)];
-	bus->sprom.boardflags_hi = sprom[SPOFF(SSB_SPROM8_BFLHI)];
-	bus->sprom.boardflags2_lo = sprom[SPOFF(SSB_SPROM8_BFL2LO)];
-	bus->sprom.boardflags2_hi = sprom[SPOFF(SSB_SPROM8_BFL2HI)];
+	SPEX(boardflags_lo, SSB_SPROM8_BFLLO, ~0, 0);
+	SPEX(boardflags_hi, SSB_SPROM8_BFLHI, ~0, 0);
+	SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, ~0, 0);
+	SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, ~0, 0);
 
-	bus->sprom.country_code = sprom[SPOFF(SSB_SPROM8_CCODE)];
+	SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8);
+	SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0);
 
-	bus->sprom.fem.ghz2.tssipos = (sprom[SPOFF(SSB_SPROM8_FEM2G)] &
-		SSB_SROM8_FEM_TSSIPOS) >> SSB_SROM8_FEM_TSSIPOS_SHIFT;
-	bus->sprom.fem.ghz2.extpa_gain = (sprom[SPOFF(SSB_SPROM8_FEM2G)] &
-		SSB_SROM8_FEM_EXTPA_GAIN) >> SSB_SROM8_FEM_EXTPA_GAIN_SHIFT;
-	bus->sprom.fem.ghz2.pdet_range = (sprom[SPOFF(SSB_SPROM8_FEM2G)] &
-		SSB_SROM8_FEM_PDET_RANGE) >> SSB_SROM8_FEM_PDET_RANGE_SHIFT;
-	bus->sprom.fem.ghz2.tr_iso = (sprom[SPOFF(SSB_SPROM8_FEM2G)] &
-		SSB_SROM8_FEM_TR_ISO) >> SSB_SROM8_FEM_TR_ISO_SHIFT;
-	bus->sprom.fem.ghz2.antswlut = (sprom[SPOFF(SSB_SPROM8_FEM2G)] &
-		SSB_SROM8_FEM_ANTSWLUT) >> SSB_SROM8_FEM_ANTSWLUT_SHIFT;
+	/* Extract cores power info info */
+	for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
+		o = pwr_info_offset[i];
+		SPEX(core_pwr_info[i].itssi_2g, o + SSB_SROM8_2G_MAXP_ITSSI,
+			SSB_SPROM8_2G_ITSSI, SSB_SPROM8_2G_ITSSI_SHIFT);
+		SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SROM8_2G_MAXP_ITSSI,
+			SSB_SPROM8_2G_MAXP, 0);
 
-	bus->sprom.fem.ghz5.tssipos = (sprom[SPOFF(SSB_SPROM8_FEM5G)] &
-		SSB_SROM8_FEM_TSSIPOS) >> SSB_SROM8_FEM_TSSIPOS_SHIFT;
-	bus->sprom.fem.ghz5.extpa_gain = (sprom[SPOFF(SSB_SPROM8_FEM5G)] &
-		SSB_SROM8_FEM_EXTPA_GAIN) >> SSB_SROM8_FEM_EXTPA_GAIN_SHIFT;
-	bus->sprom.fem.ghz5.pdet_range = (sprom[SPOFF(SSB_SPROM8_FEM5G)] &
-		SSB_SROM8_FEM_PDET_RANGE) >> SSB_SROM8_FEM_PDET_RANGE_SHIFT;
-	bus->sprom.fem.ghz5.tr_iso = (sprom[SPOFF(SSB_SPROM8_FEM5G)] &
-		SSB_SROM8_FEM_TR_ISO) >> SSB_SROM8_FEM_TR_ISO_SHIFT;
-	bus->sprom.fem.ghz5.antswlut = (sprom[SPOFF(SSB_SPROM8_FEM5G)] &
-		SSB_SROM8_FEM_ANTSWLUT) >> SSB_SROM8_FEM_ANTSWLUT_SHIFT;
+		SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SROM8_2G_PA_0, ~0, 0);
+		SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SROM8_2G_PA_1, ~0, 0);
+		SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SROM8_2G_PA_2, ~0, 0);
+
+		SPEX(core_pwr_info[i].itssi_5g, o + SSB_SROM8_5G_MAXP_ITSSI,
+			SSB_SPROM8_5G_ITSSI, SSB_SPROM8_5G_ITSSI_SHIFT);
+		SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SROM8_5G_MAXP_ITSSI,
+			SSB_SPROM8_5G_MAXP, 0);
+		SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM8_5GHL_MAXP,
+			SSB_SPROM8_5GH_MAXP, 0);
+		SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM8_5GHL_MAXP,
+			SSB_SPROM8_5GL_MAXP, SSB_SPROM8_5GL_MAXP_SHIFT);
+
+		SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SROM8_5GL_PA_0, ~0, 0);
+		SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SROM8_5GL_PA_1, ~0, 0);
+		SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SROM8_5GL_PA_2, ~0, 0);
+		SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SROM8_5G_PA_0, ~0, 0);
+		SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SROM8_5G_PA_1, ~0, 0);
+		SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SROM8_5G_PA_2, ~0, 0);
+		SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SROM8_5GH_PA_0, ~0, 0);
+		SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SROM8_5GH_PA_1, ~0, 0);
+		SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SROM8_5GH_PA_2, ~0, 0);
+	}
+
+	SPEX(fem.ghz2.tssipos, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_TSSIPOS,
+	     SSB_SROM8_FEM_TSSIPOS_SHIFT);
+	SPEX(fem.ghz2.extpa_gain, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_EXTPA_GAIN,
+	     SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
+	SPEX(fem.ghz2.pdet_range, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_PDET_RANGE,
+	     SSB_SROM8_FEM_PDET_RANGE_SHIFT);
+	SPEX(fem.ghz2.tr_iso, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_TR_ISO,
+	     SSB_SROM8_FEM_TR_ISO_SHIFT);
+	SPEX(fem.ghz2.antswlut, SSB_SPROM8_FEM2G, SSB_SROM8_FEM_ANTSWLUT,
+	     SSB_SROM8_FEM_ANTSWLUT_SHIFT);
+
+	SPEX(fem.ghz5.tssipos, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_TSSIPOS,
+	     SSB_SROM8_FEM_TSSIPOS_SHIFT);
+	SPEX(fem.ghz5.extpa_gain, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_EXTPA_GAIN,
+	     SSB_SROM8_FEM_EXTPA_GAIN_SHIFT);
+	SPEX(fem.ghz5.pdet_range, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_PDET_RANGE,
+	     SSB_SROM8_FEM_PDET_RANGE_SHIFT);
+	SPEX(fem.ghz5.tr_iso, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_TR_ISO,
+	     SSB_SROM8_FEM_TR_ISO_SHIFT);
+	SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_ANTSWLUT,
+	     SSB_SROM8_FEM_ANTSWLUT_SHIFT);
+
+	SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A,
+	     SSB_SPROM8_ANTAVAIL_A_SHIFT);
+	SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG,
+	     SSB_SPROM8_ANTAVAIL_BG_SHIFT);
+	SPEX(maxpwr_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_MAXP_BG_MASK, 0);
+	SPEX(itssi_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_ITSSI_BG,
+	     SSB_SPROM8_ITSSI_BG_SHIFT);
+	SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0);
+	SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A,
+	     SSB_SPROM8_ITSSI_A_SHIFT);
+	SPEX(maxpwr_ah, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AH_MASK, 0);
+	SPEX(maxpwr_al, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AL_MASK,
+	     SSB_SPROM8_MAXP_AL_SHIFT);
+	SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0);
+	SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1,
+	     SSB_SPROM8_GPIOA_P1_SHIFT);
+	SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0);
+	SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3,
+	     SSB_SPROM8_GPIOB_P3_SHIFT);
+	SPEX(tri2g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI2G, 0);
+	SPEX(tri5g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI5G,
+	     SSB_SPROM8_TRI5G_SHIFT);
+	SPEX(tri5gl, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GL, 0);
+	SPEX(tri5gh, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GH,
+	     SSB_SPROM8_TRI5GH_SHIFT);
+	SPEX(rxpo2g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO2G,
+	     SSB_SPROM8_RXPO2G_SHIFT);
+	SPEX(rxpo5g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO5G,
+	     SSB_SPROM8_RXPO5G_SHIFT);
+	SPEX(rssismf2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMF2G, 0);
+	SPEX(rssismc2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMC2G,
+	     SSB_SPROM8_RSSISMC2G_SHIFT);
+	SPEX(rssisav2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISAV2G,
+	     SSB_SPROM8_RSSISAV2G_SHIFT);
+	SPEX(bxa2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_BXA2G,
+	     SSB_SPROM8_BXA2G_SHIFT);
+	SPEX(rssismf5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMF5G, 0);
+	SPEX(rssismc5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMC5G,
+	     SSB_SPROM8_RSSISMC5G_SHIFT);
+	SPEX(rssisav5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISAV5G,
+	     SSB_SPROM8_RSSISAV5G_SHIFT);
+	SPEX(bxa5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_BXA5G,
+	     SSB_SPROM8_BXA5G_SHIFT);
+
+	SPEX(pa0b0, SSB_SPROM8_PA0B0, ~0, 0);
+	SPEX(pa0b1, SSB_SPROM8_PA0B1, ~0, 0);
+	SPEX(pa0b2, SSB_SPROM8_PA0B2, ~0, 0);
+	SPEX(pa1b0, SSB_SPROM8_PA1B0, ~0, 0);
+	SPEX(pa1b1, SSB_SPROM8_PA1B1, ~0, 0);
+	SPEX(pa1b2, SSB_SPROM8_PA1B2, ~0, 0);
+	SPEX(pa1lob0, SSB_SPROM8_PA1LOB0, ~0, 0);
+	SPEX(pa1lob1, SSB_SPROM8_PA1LOB1, ~0, 0);
+	SPEX(pa1lob2, SSB_SPROM8_PA1LOB2, ~0, 0);
+	SPEX(pa1hib0, SSB_SPROM8_PA1HIB0, ~0, 0);
+	SPEX(pa1hib1, SSB_SPROM8_PA1HIB1, ~0, 0);
+	SPEX(pa1hib2, SSB_SPROM8_PA1HIB2, ~0, 0);
+	SPEX(cck2gpo, SSB_SPROM8_CCK2GPO, ~0, 0);
+	SPEX32(ofdm2gpo, SSB_SPROM8_OFDM2GPO, ~0, 0);
+	SPEX32(ofdm5glpo, SSB_SPROM8_OFDM5GLPO, ~0, 0);
+	SPEX32(ofdm5gpo, SSB_SPROM8_OFDM5GPO, ~0, 0);
+	SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, ~0, 0);
+
+	/* Extract the antenna gain values. */
+	SPEX(antenna_gain.a0, SSB_SPROM8_AGAIN01,
+	     SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT);
+	SPEX(antenna_gain.a1, SSB_SPROM8_AGAIN01,
+	     SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT);
+	SPEX(antenna_gain.a2, SSB_SPROM8_AGAIN23,
+	     SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT);
+	SPEX(antenna_gain.a3, SSB_SPROM8_AGAIN23,
+	     SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT);
+
+	SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON,
+	     SSB_SPROM8_LEDDC_ON_SHIFT);
+	SPEX(leddc_off_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_OFF,
+	     SSB_SPROM8_LEDDC_OFF_SHIFT);
+
+	SPEX(txchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_TXCHAIN,
+	     SSB_SPROM8_TXRXC_TXCHAIN_SHIFT);
+	SPEX(rxchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_RXCHAIN,
+	     SSB_SPROM8_TXRXC_RXCHAIN_SHIFT);
+	SPEX(antswitch, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_SWITCH,
+	     SSB_SPROM8_TXRXC_SWITCH_SHIFT);
+
+	SPEX(opo, SSB_SPROM8_OFDM2GPO, 0x00ff, 0);
+
+	SPEX_ARRAY8(mcs2gpo, SSB_SPROM8_2G_MCSPO, ~0, 0);
+	SPEX_ARRAY8(mcs5gpo, SSB_SPROM8_5G_MCSPO, ~0, 0);
+	SPEX_ARRAY8(mcs5glpo, SSB_SPROM8_5GL_MCSPO, ~0, 0);
+	SPEX_ARRAY8(mcs5ghpo, SSB_SPROM8_5GH_MCSPO, ~0, 0);
+
+	SPEX(rawtempsense, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_RAWTEMP,
+	     SSB_SPROM8_RAWTS_RAWTEMP_SHIFT);
+	SPEX(measpower, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_MEASPOWER,
+	     SSB_SPROM8_RAWTS_MEASPOWER_SHIFT);
+	SPEX(tempsense_slope, SSB_SPROM8_OPT_CORRX,
+	     SSB_SPROM8_OPT_CORRX_TEMP_SLOPE,
+	     SSB_SPROM8_OPT_CORRX_TEMP_SLOPE_SHIFT);
+	SPEX(tempcorrx, SSB_SPROM8_OPT_CORRX, SSB_SPROM8_OPT_CORRX_TEMPCORRX,
+	     SSB_SPROM8_OPT_CORRX_TEMPCORRX_SHIFT);
+	SPEX(tempsense_option, SSB_SPROM8_OPT_CORRX,
+	     SSB_SPROM8_OPT_CORRX_TEMP_OPTION,
+	     SSB_SPROM8_OPT_CORRX_TEMP_OPTION_SHIFT);
+	SPEX(freqoffset_corr, SSB_SPROM8_HWIQ_IQSWP,
+	     SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR,
+	     SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR_SHIFT);
+	SPEX(iqcal_swp_dis, SSB_SPROM8_HWIQ_IQSWP,
+	     SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP,
+	     SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT);
+	SPEX(hw_iqcal_en, SSB_SPROM8_HWIQ_IQSWP, SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL,
+	     SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT);
+
+	SPEX(bw40po, SSB_SPROM8_BW40PO, ~0, 0);
+	SPEX(cddpo, SSB_SPROM8_CDDPO, ~0, 0);
+	SPEX(stbcpo, SSB_SPROM8_STBCPO, ~0, 0);
+	SPEX(bwduppo, SSB_SPROM8_BWDUPPO, ~0, 0);
+
+	SPEX(tempthresh, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_TRESH,
+	     SSB_SPROM8_THERMAL_TRESH_SHIFT);
+	SPEX(tempoffset, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_OFFSET,
+	     SSB_SPROM8_THERMAL_OFFSET_SHIFT);
+	SPEX(phycal_tempdelta, SSB_SPROM8_TEMPDELTA,
+	     SSB_SPROM8_TEMPDELTA_PHYCAL,
+	     SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT);
+	SPEX(temps_period, SSB_SPROM8_TEMPDELTA, SSB_SPROM8_TEMPDELTA_PERIOD,
+	     SSB_SPROM8_TEMPDELTA_PERIOD_SHIFT);
+	SPEX(temps_hysteresis, SSB_SPROM8_TEMPDELTA,
+	     SSB_SPROM8_TEMPDELTA_HYSTERESIS,
+	     SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT);
+}
+
+/*
+ * Indicates the presence of external SPROM.
+ */
+static bool bcma_sprom_ext_available(struct bcma_bus *bus)
+{
+	u32 chip_status;
+	u32 srom_control;
+	u32 present_mask;
+
+	if (bus->drv_cc.core->id.rev >= 31) {
+		if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM))
+			return false;
+
+		srom_control = bcma_read32(bus->drv_cc.core,
+					   BCMA_CC_SROM_CONTROL);
+		return srom_control & BCMA_CC_SROM_CONTROL_PRESENT;
+	}
+
+	/* older chipcommon revisions use chip status register */
+	chip_status = bcma_read32(bus->drv_cc.core, BCMA_CC_CHIPSTAT);
+	switch (bus->chipinfo.id) {
+	case BCMA_CHIP_ID_BCM4313:
+		present_mask = BCMA_CC_CHIPST_4313_SPROM_PRESENT;
+		break;
+
+	case BCMA_CHIP_ID_BCM4331:
+		present_mask = BCMA_CC_CHIPST_4331_SPROM_PRESENT;
+		break;
+
+	default:
+		return true;
+	}
+
+	return chip_status & present_mask;
+}
+
+/*
+ * Indicates that on-chip OTP memory is present and enabled.
+ */
+static bool bcma_sprom_onchip_available(struct bcma_bus *bus)
+{
+	u32 chip_status;
+	u32 otpsize = 0;
+	bool present;
+
+	chip_status = bcma_read32(bus->drv_cc.core, BCMA_CC_CHIPSTAT);
+	switch (bus->chipinfo.id) {
+	case BCMA_CHIP_ID_BCM4313:
+		present = chip_status & BCMA_CC_CHIPST_4313_OTP_PRESENT;
+		break;
+
+	case BCMA_CHIP_ID_BCM4331:
+		present = chip_status & BCMA_CC_CHIPST_4331_OTP_PRESENT;
+		break;
+
+	case BCMA_CHIP_ID_BCM43224:
+	case BCMA_CHIP_ID_BCM43225:
+		/* for these chips OTP is always available */
+		present = true;
+		break;
+
+	default:
+		present = false;
+		break;
+	}
+
+	if (present) {
+		otpsize = bus->drv_cc.capabilities & BCMA_CC_CAP_OTPS;
+		otpsize >>= BCMA_CC_CAP_OTPS_SHIFT;
+	}
+
+	return otpsize != 0;
+}
+
+/*
+ * Verify OTP is filled and determine the byte
+ * offset where SPROM data is located.
+ *
+ * On error, returns 0; byte offset otherwise.
+ */
+static int bcma_sprom_onchip_offset(struct bcma_bus *bus)
+{
+	struct bcma_device *cc = bus->drv_cc.core;
+	u32 offset;
+
+	/* verify OTP status */
+	if ((bcma_read32(cc, BCMA_CC_OTPS) & BCMA_CC_OTPS_GU_PROG_HW) == 0)
+		return 0;
+
+	/* obtain bit offset from otplayout register */
+	offset = (bcma_read32(cc, BCMA_CC_OTPL) & BCMA_CC_OTPL_GURGN_OFFSET);
+	return BCMA_CC_SPROM + (offset >> 3);
 }
 
 int bcma_sprom_get(struct bcma_bus *bus)
 {
-	u16 offset;
+	u16 offset = BCMA_CC_SPROM;
 	u16 *sprom;
 	int err = 0;
 
 	if (!bus->drv_cc.core)
 		return -EOPNOTSUPP;
 
-	if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM))
-		return -ENOENT;
+	if (!bcma_sprom_ext_available(bus)) {
+		bool sprom_onchip;
+
+		/*
+		 * External SPROM takes precedence so check
+		 * on-chip OTP only when no external SPROM
+		 * is present.
+		 */
+		sprom_onchip = bcma_sprom_onchip_available(bus);
+		if (sprom_onchip) {
+			/* determine offset */
+			offset = bcma_sprom_onchip_offset(bus);
+		}
+		if (!offset || !sprom_onchip) {
+			/*
+			 * Maybe there is no SPROM on the device?
+			 * Now we ask the arch code if there is some sprom
+			 * available for this device in some other storage.
+			 */
+			err = bcma_fill_sprom_with_fallback(bus, &bus->sprom);
+			return err;
+		}
+	}
 
 	sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
 			GFP_KERNEL);
 	if (!sprom)
 		return -ENOMEM;
 
-	if (bus->chipinfo.id == 0x4331)
+	if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4331 ||
+	    bus->chipinfo.id == BCMA_CHIP_ID_BCM43431)
 		bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false);
 
-	/* Most cards have SPROM moved by additional offset 0x30 (48 dwords).
-	 * According to brcm80211 this applies to cards with PCIe rev >= 6
-	 * TODO: understand this condition and use it */
-	offset = (bus->chipinfo.id == 0x4331) ? BCMA_CC_SPROM :
-		BCMA_CC_SPROM_PCIE6;
+	bcma_debug(bus, "SPROM offset 0x%x\n", offset);
 	bcma_sprom_read(bus, offset, sprom);
 
-	if (bus->chipinfo.id == 0x4331)
+	if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4331 ||
+	    bus->chipinfo.id == BCMA_CHIP_ID_BCM43431)
 		bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true);
 
 	err = bcma_sprom_valid(sprom);
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index 2f22874..1249cf3 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -852,9 +852,8 @@
 	if (err)
 		goto fail;
 
-	err = bind_evtchn_to_irqhandler(info->evtchn,
-					blkif_interrupt,
-					IRQF_SAMPLE_RANDOM, "blkif", info);
+	err = bind_evtchn_to_irqhandler(info->evtchn, blkif_interrupt, 0,
+					"blkif", info);
 	if (err <= 0) {
 		xenbus_dev_fatal(dev, err,
 				 "bind_evtchn_to_irqhandler failed");
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c
index ae9edca..287e3c2 100644
--- a/drivers/bluetooth/ath3k.c
+++ b/drivers/bluetooth/ath3k.c
@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2013 The Linux Foundation. All rights reserved.
  * Copyright (c) 2008-2009 Atheros Communications Inc.
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -286,7 +287,7 @@
 	}
 
 	snprintf(filename, ATH3K_NAME_LEN, "ar3k/AthrBT_0x%08x.dfu",
-		fw_version.rom_version);
+		le32_to_cpu(fw_version.rom_version));
 
 	ret = request_firmware(&firmware, filename, &udev->dev);
 	if (ret < 0) {
@@ -348,7 +349,7 @@
 	}
 
 	snprintf(filename, ATH3K_NAME_LEN, "ar3k/ramps_0x%08x_%d%s",
-		fw_version.rom_version, clk_value, ".dfu");
+		le32_to_cpu(fw_version.rom_version), clk_value, ".dfu");
 
 	ret = request_firmware(&firmware, filename, &udev->dev);
 	if (ret < 0) {
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 4364303..fdea8e0 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -511,6 +511,14 @@
 	  pc8736x_gpio drivers.  If those drivers are built as
 	  modules, this one will be too, named nsc_gpio
 
+config GPIO_DEVICE
+	tristate "GPIO device support"
+	depends on GENERIC_GPIO
+	help
+	  Say Y to enable Linux GPIO device support.  This allows control of
+	  GPIO pins using a character device
+
+
 config RAW_DRIVER
 	tristate "RAW driver (/dev/raw/rawN)"
 	depends on BLOCK
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 32762ba..7056753 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -47,6 +47,7 @@
 obj-$(CONFIG_SCx200_GPIO)	+= scx200_gpio.o
 obj-$(CONFIG_PC8736x_GPIO)	+= pc8736x_gpio.o
 obj-$(CONFIG_NSC_GPIO)		+= nsc_gpio.o
+obj-$(CONFIG_GPIO_DEVICE)	+= gpio_dev.o
 obj-$(CONFIG_GPIO_TB0219)	+= tb0219.o
 obj-$(CONFIG_TELCLOCK)		+= tlclk.o
 
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 54ca8b2..5c4fb9a 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -125,21 +125,29 @@
  * The current exported interfaces for gathering environmental noise
  * from the devices are:
  *
+ *	void add_device_randomness(const void *buf, unsigned int size);
  * 	void add_input_randomness(unsigned int type, unsigned int code,
  *                                unsigned int value);
- * 	void add_interrupt_randomness(int irq);
+ *	void add_interrupt_randomness(int irq, int irq_flags);
  * 	void add_disk_randomness(struct gendisk *disk);
  *
+ *      void random_input_words(__u32 *buf, size_t wordcount, int ent_count)
+ *      int random_input_wait(void);
+ *
  * add_input_randomness() uses the input layer interrupt timing, as well as
  * the event type information from the hardware.
  *
- * add_interrupt_randomness() uses the inter-interrupt timing as random
- * inputs to the entropy pool.  Note that not all interrupts are good
- * sources of randomness!  For example, the timer interrupts is not a
- * good choice, because the periodicity of the interrupts is too
- * regular, and hence predictable to an attacker.  Network Interface
- * Controller interrupts are a better measure, since the timing of the
- * NIC interrupts are more unpredictable.
+ * add_interrupt_randomness() uses the interrupt timing as random
+ * inputs to the entropy pool. Using the cycle counters and the irq source
+ * as inputs, it feeds the randomness roughly once a second.
+ *
+ * add_device_randomness() is for adding data to the random pool that
+ * is likely to differ between two devices (or possibly even per boot).
+ * This would be things like MAC addresses or serial numbers, or the
+ * read-out of the RTC. This does *not* add any actual entropy to the
+ * pool, but it initializes the pool to different values for devices
+ * that might otherwise be identical and have very little entropy
+ * available to them (particularly common in the embedded world).
  *
  * add_disk_randomness() uses what amounts to the seek time of block
  * layer request events, on a per-disk_devt basis, as input to the
@@ -147,6 +155,13 @@
  * seek times do not make for good sources of entropy, as their seek
  * times are usually fairly consistent.
  *
+ * random_input_words() just provides a raw block of entropy to the input
+ * pool, such as from a hardware entropy generator.
+ *
+ * random_input_wait() suspends the caller until such time as the
+ * entropy pool falls below the write threshold, and returns a count of how
+ * much entropy (in bits) is needed to sustain the pool.
+ *
  * All of these routines try to estimate how many bits of randomness a
  * particular randomness source.  They do this by keeping track of the
  * first and second order deltas of the event timings.
@@ -248,6 +263,7 @@
 #include <linux/percpu.h>
 #include <linux/cryptohash.h>
 #include <linux/fips.h>
+#include <linux/ptrace.h>
 
 #ifdef CONFIG_GENERIC_HARDIRQS
 # include <linux/irq.h>
@@ -256,8 +272,12 @@
 #include <asm/processor.h>
 #include <asm/uaccess.h>
 #include <asm/irq.h>
+#include <asm/irq_regs.h>
 #include <asm/io.h>
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/random.h>
+
 /*
  * Configuration information
  */
@@ -420,8 +440,10 @@
 	/* read-write data: */
 	spinlock_t lock;
 	unsigned add_ptr;
+	unsigned input_rotate;
 	int entropy_count;
-	int input_rotate;
+	int entropy_total;
+	unsigned int initialized:1;
 	__u8 last_data[EXTRACT_SIZE];
 };
 
@@ -454,6 +476,10 @@
 	.pool = nonblocking_pool_data
 };
 
+static __u32 const twist_table[8] = {
+	0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
+	0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 };
+
 /*
  * This function adds bytes into the entropy "pool".  It does not
  * update the entropy estimate.  The caller should call
@@ -464,29 +490,24 @@
  * it's cheap to do so and helps slightly in the expected case where
  * the entropy is concentrated in the low-order bits.
  */
-static void mix_pool_bytes_extract(struct entropy_store *r, const void *in,
-				   int nbytes, __u8 out[64])
+static void _mix_pool_bytes(struct entropy_store *r, const void *in,
+			    int nbytes, __u8 out[64])
 {
-	static __u32 const twist_table[8] = {
-		0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
-		0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 };
 	unsigned long i, j, tap1, tap2, tap3, tap4, tap5;
 	int input_rotate;
 	int wordmask = r->poolinfo->poolwords - 1;
 	const char *bytes = in;
 	__u32 w;
-	unsigned long flags;
 
-	/* Taps are constant, so we can load them without holding r->lock.  */
 	tap1 = r->poolinfo->tap1;
 	tap2 = r->poolinfo->tap2;
 	tap3 = r->poolinfo->tap3;
 	tap4 = r->poolinfo->tap4;
 	tap5 = r->poolinfo->tap5;
 
-	spin_lock_irqsave(&r->lock, flags);
-	input_rotate = r->input_rotate;
-	i = r->add_ptr;
+	smp_rmb();
+	input_rotate = ACCESS_ONCE(r->input_rotate);
+	i = ACCESS_ONCE(r->add_ptr);
 
 	/* mix one byte at a time to simplify size handling and churn faster */
 	while (nbytes--) {
@@ -513,19 +534,61 @@
 		input_rotate += i ? 7 : 14;
 	}
 
-	r->input_rotate = input_rotate;
-	r->add_ptr = i;
+	ACCESS_ONCE(r->input_rotate) = input_rotate;
+	ACCESS_ONCE(r->add_ptr) = i;
+	smp_wmb();
 
 	if (out)
 		for (j = 0; j < 16; j++)
 			((__u32 *)out)[j] = r->pool[(i - j) & wordmask];
+}
 
+static void __mix_pool_bytes(struct entropy_store *r, const void *in,
+			     int nbytes, __u8 out[64])
+{
+	trace_mix_pool_bytes_nolock(r->name, nbytes, _RET_IP_);
+	_mix_pool_bytes(r, in, nbytes, out);
+}
+
+static void mix_pool_bytes(struct entropy_store *r, const void *in,
+			   int nbytes, __u8 out[64])
+{
+	unsigned long flags;
+
+	trace_mix_pool_bytes(r->name, nbytes, _RET_IP_);
+	spin_lock_irqsave(&r->lock, flags);
+	_mix_pool_bytes(r, in, nbytes, out);
 	spin_unlock_irqrestore(&r->lock, flags);
 }
 
-static void mix_pool_bytes(struct entropy_store *r, const void *in, int bytes)
+struct fast_pool {
+	__u32		pool[4];
+	unsigned long	last;
+	unsigned short	count;
+	unsigned char	rotate;
+	unsigned char	last_timer_intr;
+};
+
+/*
+ * This is a fast mixing routine used by the interrupt randomness
+ * collector.  It's hardcoded for an 128 bit pool and assumes that any
+ * locks that might be needed are taken by the caller.
+ */
+static void fast_mix(struct fast_pool *f, const void *in, int nbytes)
 {
-       mix_pool_bytes_extract(r, in, bytes, NULL);
+	const char	*bytes = in;
+	__u32		w;
+	unsigned	i = f->count;
+	unsigned	input_rotate = f->rotate;
+
+	while (nbytes--) {
+		w = rol32(*bytes++, input_rotate & 31) ^ f->pool[i & 3] ^
+			f->pool[(i + 1) & 3];
+		f->pool[i & 3] = (w >> 3) ^ twist_table[w & 7];
+		input_rotate += (i++ & 3) ? 7 : 14;
+	}
+	f->count = i;
+	f->rotate = input_rotate;
 }
 
 /*
@@ -533,30 +596,38 @@
  */
 static void credit_entropy_bits(struct entropy_store *r, int nbits)
 {
-	unsigned long flags;
-	int entropy_count;
+	int entropy_count, orig;
 
 	if (!nbits)
 		return;
 
-	spin_lock_irqsave(&r->lock, flags);
-
 	DEBUG_ENT("added %d entropy credits to %s\n", nbits, r->name);
-	entropy_count = r->entropy_count;
+retry:
+	entropy_count = orig = ACCESS_ONCE(r->entropy_count);
 	entropy_count += nbits;
+
 	if (entropy_count < 0) {
 		DEBUG_ENT("negative entropy/overflow\n");
 		entropy_count = 0;
 	} else if (entropy_count > r->poolinfo->POOLBITS)
 		entropy_count = r->poolinfo->POOLBITS;
-	r->entropy_count = entropy_count;
+	if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
+		goto retry;
+
+	if (!r->initialized && nbits > 0) {
+		r->entropy_total += nbits;
+		if (r->entropy_total > 128)
+			r->initialized = 1;
+	}
+
+	trace_credit_entropy_bits(r->name, nbits, entropy_count,
+				  r->entropy_total, _RET_IP_);
 
 	/* should we wake readers? */
 	if (r == &input_pool && entropy_count >= random_read_wakeup_thresh) {
 		wake_up_interruptible(&random_read_wait);
 		kill_fasync(&fasync, SIGIO, POLL_IN);
 	}
-	spin_unlock_irqrestore(&r->lock, flags);
 }
 
 /*********************************************************************
@@ -572,42 +643,24 @@
 	unsigned dont_count_entropy:1;
 };
 
-#ifndef CONFIG_GENERIC_HARDIRQS
-
-static struct timer_rand_state *irq_timer_state[NR_IRQS];
-
-static struct timer_rand_state *get_timer_rand_state(unsigned int irq)
+/*
+ * Add device- or boot-specific data to the input and nonblocking
+ * pools to help initialize them to unique values.
+ *
+ * None of this adds any entropy, it is meant to avoid the
+ * problem of the nonblocking pool having similar initial state
+ * across largely identical devices.
+ */
+void add_device_randomness(const void *buf, unsigned int size)
 {
-	return irq_timer_state[irq];
+	unsigned long time = get_cycles() ^ jiffies;
+
+	mix_pool_bytes(&input_pool, buf, size, NULL);
+	mix_pool_bytes(&input_pool, &time, sizeof(time), NULL);
+	mix_pool_bytes(&nonblocking_pool, buf, size, NULL);
+	mix_pool_bytes(&nonblocking_pool, &time, sizeof(time), NULL);
 }
-
-static void set_timer_rand_state(unsigned int irq,
-				 struct timer_rand_state *state)
-{
-	irq_timer_state[irq] = state;
-}
-
-#else
-
-static struct timer_rand_state *get_timer_rand_state(unsigned int irq)
-{
-	struct irq_desc *desc;
-
-	desc = irq_to_desc(irq);
-
-	return desc->timer_rand_state;
-}
-
-static void set_timer_rand_state(unsigned int irq,
-				 struct timer_rand_state *state)
-{
-	struct irq_desc *desc;
-
-	desc = irq_to_desc(irq);
-
-	desc->timer_rand_state = state;
-}
-#endif
+EXPORT_SYMBOL(add_device_randomness);
 
 static struct timer_rand_state input_timer_state;
 
@@ -637,13 +690,9 @@
 		goto out;
 
 	sample.jiffies = jiffies;
-
-	/* Use arch random value, fall back to cycles */
-	if (!arch_get_random_int(&sample.cycles))
-		sample.cycles = get_cycles();
-
+	sample.cycles = get_cycles();
 	sample.num = num;
-	mix_pool_bytes(&input_pool, &sample, sizeof(sample));
+	mix_pool_bytes(&input_pool, &sample, sizeof(sample), NULL);
 
 	/*
 	 * Calculate number of bits of randomness we probably added.
@@ -700,17 +749,48 @@
 }
 EXPORT_SYMBOL_GPL(add_input_randomness);
 
-void add_interrupt_randomness(int irq)
+static DEFINE_PER_CPU(struct fast_pool, irq_randomness);
+
+void add_interrupt_randomness(int irq, int irq_flags)
 {
-	struct timer_rand_state *state;
+	struct entropy_store	*r;
+	struct fast_pool	*fast_pool = &__get_cpu_var(irq_randomness);
+	struct pt_regs		*regs = get_irq_regs();
+	unsigned long		now = jiffies;
+	__u32			input[4], cycles = get_cycles();
 
-	state = get_timer_rand_state(irq);
+	input[0] = cycles ^ jiffies;
+	input[1] = irq;
+	if (regs) {
+		__u64 ip = instruction_pointer(regs);
+		input[2] = ip;
+		input[3] = ip >> 32;
+	}
 
-	if (state == NULL)
+	fast_mix(fast_pool, input, sizeof(input));
+
+	if ((fast_pool->count & 1023) &&
+	    !time_after(now, fast_pool->last + HZ))
 		return;
 
-	DEBUG_ENT("irq event %d\n", irq);
-	add_timer_randomness(state, 0x100 + irq);
+	fast_pool->last = now;
+
+	r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool;
+	__mix_pool_bytes(r, &fast_pool->pool, sizeof(fast_pool->pool), NULL);
+	/*
+	 * If we don't have a valid cycle counter, and we see
+	 * back-to-back timer interrupts, then skip giving credit for
+	 * any entropy.
+	 */
+	if (cycles == 0) {
+		if (irq_flags & __IRQF_TIMER) {
+			if (fast_pool->last_timer_intr)
+				return;
+			fast_pool->last_timer_intr = 1;
+		} else
+			fast_pool->last_timer_intr = 0;
+	}
+	credit_entropy_bits(r, 1);
 }
 
 #ifdef CONFIG_BLOCK
@@ -726,6 +806,63 @@
 }
 #endif
 
+/*
+ * random_input_words - add bulk entropy to pool
+ *
+ * @buf: buffer to add
+ * @wordcount: number of __u32 words to add
+ * @ent_count: total amount of entropy (in bits) to credit
+ *
+ * this provides bulk input of entropy to the input pool
+ *
+ */
+void random_input_words(__u32 *buf, size_t wordcount, int ent_count)
+{
+	mix_pool_bytes(&input_pool, buf, wordcount*4, NULL);
+
+	credit_entropy_bits(&input_pool, ent_count);
+
+	DEBUG_ENT("crediting %d bits => %d\n",
+		  ent_count, input_pool.entropy_count);
+	/*
+	 * Wake up waiting processes if we have enough
+	 * entropy.
+	 */
+	if (input_pool.entropy_count >= random_read_wakeup_thresh)
+		wake_up_interruptible(&random_read_wait);
+}
+EXPORT_SYMBOL(random_input_words);
+
+/*
+ * random_input_wait - wait until random needs entropy
+ *
+ * this function sleeps until the /dev/random subsystem actually
+ * needs more entropy, and then return the amount of entropy
+ * that it would be nice to have added to the system.
+ */
+int random_input_wait(void)
+{
+	int count;
+
+	wait_event_interruptible(random_write_wait, 
+			 input_pool.entropy_count < random_write_wakeup_thresh);
+
+	count = random_write_wakeup_thresh - input_pool.entropy_count;
+
+        /* likely we got woken up due to a signal */
+	if (count <= 0) count = random_read_wakeup_thresh; 
+
+	DEBUG_ENT("requesting %d bits from input_wait()er %d<%d\n",
+		  count,
+		  input_pool.entropy_count, random_write_wakeup_thresh);
+
+	return count;
+}
+EXPORT_SYMBOL(random_input_wait);
+
+
+#define EXTRACT_SIZE 10
+
 /*********************************************************************
  *
  * Entropy extraction routines
@@ -742,7 +879,11 @@
  */
 static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
 {
-	__u32 tmp[OUTPUT_POOL_WORDS];
+	union {
+		__u32	tmp[OUTPUT_POOL_WORDS];
+		long	hwrand[4];
+	} u;
+	int	i;
 
 	if (r->pull && r->entropy_count < nbytes * 8 &&
 	    r->entropy_count < r->poolinfo->POOLBITS) {
@@ -753,17 +894,22 @@
 		/* pull at least as many as BYTES as wakeup BITS */
 		bytes = max_t(int, bytes, random_read_wakeup_thresh / 8);
 		/* but never more than the buffer size */
-		bytes = min_t(int, bytes, sizeof(tmp));
+		bytes = min_t(int, bytes, sizeof(u.tmp));
 
 		DEBUG_ENT("going to reseed %s with %d bits "
 			  "(%d of %d requested)\n",
 			  r->name, bytes * 8, nbytes * 8, r->entropy_count);
 
-		bytes = extract_entropy(r->pull, tmp, bytes,
+		bytes = extract_entropy(r->pull, u.tmp, bytes,
 					random_read_wakeup_thresh / 8, rsvd);
-		mix_pool_bytes(r, tmp, bytes);
+		mix_pool_bytes(r, u.tmp, bytes, NULL);
 		credit_entropy_bits(r, bytes*8);
 	}
+	for (i = 0; i < 4; i++)
+		if (arch_get_random_long(&u.hwrand[i]))
+			break;
+	if (i)
+		mix_pool_bytes(r, &u.hwrand, i * sizeof(u.hwrand[0]), 0);
 }
 
 /*
@@ -822,9 +968,11 @@
 	int i;
 	__u32 hash[5], workspace[SHA_WORKSPACE_WORDS];
 	__u8 extract[64];
+	unsigned long flags;
 
 	/* Generate a hash across the pool, 16 words (512 bits) at a time */
 	sha_init(hash);
+	spin_lock_irqsave(&r->lock, flags);
 	for (i = 0; i < r->poolinfo->poolwords; i += 16)
 		sha_transform(hash, (__u8 *)(r->pool + i), workspace);
 
@@ -837,7 +985,8 @@
 	 * brute-forcing the feedback as hard as brute-forcing the
 	 * hash.
 	 */
-	mix_pool_bytes_extract(r, hash, sizeof(hash), extract);
+	__mix_pool_bytes(r, hash, sizeof(hash), extract);
+	spin_unlock_irqrestore(&r->lock, flags);
 
 	/*
 	 * To avoid duplicates, we atomically extract a portion of the
@@ -860,12 +1009,12 @@
 }
 
 static ssize_t extract_entropy(struct entropy_store *r, void *buf,
-			       size_t nbytes, int min, int reserved)
+				 size_t nbytes, int min, int reserved)
 {
 	ssize_t ret = 0, i;
 	__u8 tmp[EXTRACT_SIZE];
-	unsigned long flags;
 
+	trace_extract_entropy(r->name, nbytes, r->entropy_count, _RET_IP_);
 	xfer_secondary_pool(r, nbytes);
 	nbytes = account(r, nbytes, min, reserved);
 
@@ -873,6 +1022,8 @@
 		extract_buf(r, tmp);
 
 		if (fips_enabled) {
+			unsigned long flags;
+
 			spin_lock_irqsave(&r->lock, flags);
 			if (!memcmp(tmp, r->last_data, EXTRACT_SIZE))
 				panic("Hardware RNG duplicated output!\n");
@@ -898,6 +1049,7 @@
 	ssize_t ret = 0, i;
 	__u8 tmp[EXTRACT_SIZE];
 
+	trace_extract_entropy_user(r->name, nbytes, r->entropy_count, _RET_IP_);
 	xfer_secondary_pool(r, nbytes);
 	nbytes = account(r, nbytes, 0, 0);
 
@@ -931,17 +1083,35 @@
 
 /*
  * This function is the exported kernel interface.  It returns some
- * number of good random numbers, suitable for seeding TCP sequence
- * numbers, etc.
+ * number of good random numbers, suitable for key generation, seeding
+ * TCP sequence numbers, etc.  It does not use the hw random number
+ * generator, if available; use get_random_bytes_arch() for that.
  */
 void get_random_bytes(void *buf, int nbytes)
 {
+	extract_entropy(&nonblocking_pool, buf, nbytes, 0, 0);
+}
+EXPORT_SYMBOL(get_random_bytes);
+
+/*
+ * This function will use the architecture-specific hardware random
+ * number generator if it is available.  The arch-specific hw RNG will
+ * almost certainly be faster than what we can do in software, but it
+ * is impossible to verify that it is implemented securely (as
+ * opposed, to, say, the AES encryption of a sequence number using a
+ * key known by the NSA).  So it's useful if we need the speed, but
+ * only if we're willing to trust the hardware manufacturer not to
+ * have put in a back door.
+ */
+void get_random_bytes_arch(void *buf, int nbytes)
+{
 	char *p = buf;
 
+	trace_get_random_bytes(nbytes, _RET_IP_);
 	while (nbytes) {
 		unsigned long v;
 		int chunk = min(nbytes, (int)sizeof(unsigned long));
-		
+
 		if (!arch_get_random_long(&v))
 			break;
 		
@@ -950,9 +1120,11 @@
 		nbytes -= chunk;
 	}
 
-	extract_entropy(&nonblocking_pool, p, nbytes, 0, 0);
+	if (nbytes)
+		extract_entropy(&nonblocking_pool, p, nbytes, 0, 0);
 }
-EXPORT_SYMBOL(get_random_bytes);
+EXPORT_SYMBOL(get_random_bytes_arch);
+
 
 /*
  * init_std_data - initialize pool with system data
@@ -966,21 +1138,18 @@
 static void init_std_data(struct entropy_store *r)
 {
 	int i;
-	ktime_t now;
-	unsigned long flags;
+	ktime_t now = ktime_get_real();
+	unsigned long rv;
 
-	spin_lock_irqsave(&r->lock, flags);
 	r->entropy_count = 0;
-	spin_unlock_irqrestore(&r->lock, flags);
-
-	now = ktime_get_real();
-	mix_pool_bytes(r, &now, sizeof(now));
-	for (i = r->poolinfo->POOLBYTES; i > 0; i -= sizeof flags) {
-		if (!arch_get_random_long(&flags))
+	r->entropy_total = 0;
+	mix_pool_bytes(r, &now, sizeof(now), NULL);
+	for (i = r->poolinfo->POOLBYTES; i > 0; i -= sizeof(rv)) {
+		if (!arch_get_random_long(&rv))
 			break;
-		mix_pool_bytes(r, &flags, sizeof(flags));
+		mix_pool_bytes(r, &rv, sizeof(rv), NULL);
 	}
-	mix_pool_bytes(r, utsname(), sizeof(*(utsname())));
+	mix_pool_bytes(r, utsname(), sizeof(*(utsname())), NULL);
 }
 
 static int rand_initialize(void)
@@ -992,24 +1161,6 @@
 }
 module_init(rand_initialize);
 
-void rand_initialize_irq(int irq)
-{
-	struct timer_rand_state *state;
-
-	state = get_timer_rand_state(irq);
-
-	if (state)
-		return;
-
-	/*
-	 * If kzalloc returns null, we just won't use that entropy
-	 * source.
-	 */
-	state = kzalloc(sizeof(struct timer_rand_state), GFP_KERNEL);
-	if (state)
-		set_timer_rand_state(irq, state);
-}
-
 #ifdef CONFIG_BLOCK
 void rand_initialize_disk(struct gendisk *disk)
 {
@@ -1117,7 +1268,7 @@
 		count -= bytes;
 		p += bytes;
 
-		mix_pool_bytes(r, buf, bytes);
+		mix_pool_bytes(r, buf, bytes, NULL);
 		cond_resched();
 	}
 
@@ -1274,6 +1425,7 @@
 }
 
 static int sysctl_poolsize = INPUT_POOL_WORDS * 32;
+extern ctl_table random_table[];
 ctl_table random_table[] = {
 	{
 		.procname	= "poolsize",
@@ -1339,7 +1491,7 @@
  * value is not cryptographically secure but for several uses the cost of
  * depleting entropy is too high
  */
-DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash);
+static DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash);
 unsigned int get_random_int(void)
 {
 	__u32 *hash;
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 7e3002b..e356662 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -172,6 +172,7 @@
 	depends on PLAT_ORION
 	select CRYPTO_ALGAPI
 	select CRYPTO_AES
+	select CRYPTO_HASH2
 	select CRYPTO_BLKCIPHER2
 	select CRYPTO_HASH
 	help
diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c
index 13f8e1a..5cbe289 100644
--- a/drivers/crypto/amcc/crypto4xx_core.c
+++ b/drivers/crypto/amcc/crypto4xx_core.c
@@ -19,6 +19,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/spinlock_types.h>
 #include <linux/random.h>
diff --git a/drivers/crypto/hifn_795x.c b/drivers/crypto/hifn_795x.c
index fe765f4..9ce0f9f 100644
--- a/drivers/crypto/hifn_795x.c
+++ b/drivers/crypto/hifn_795x.c
@@ -682,12 +682,12 @@
 
 static inline void hifn_write_0(struct hifn_device *dev, u32 reg, u32 val)
 {
-	writel((__force u32)cpu_to_le32(val), dev->bar[0] + reg);
+	writel(val, dev->bar[0] + reg);
 }
 
 static inline void hifn_write_1(struct hifn_device *dev, u32 reg, u32 val)
 {
-	writel((__force u32)cpu_to_le32(val), dev->bar[1] + reg);
+	writel(val, dev->bar[1] + reg);
 }
 
 static void hifn_wait_puc(struct hifn_device *dev)
diff --git a/drivers/crypto/n2_core.c b/drivers/crypto/n2_core.c
index 8944dab..696a814 100644
--- a/drivers/crypto/n2_core.c
+++ b/drivers/crypto/n2_core.c
@@ -1607,8 +1607,7 @@
 
 	sprintf(p->irq_name, "%s-%d", irq_name, index);
 
-	return request_irq(p->irq, handler, IRQF_SAMPLE_RANDOM,
-			   p->irq_name, p);
+	return request_irq(p->irq, handler, 0, p->irq_name, p);
 }
 
 static struct kmem_cache *queue_cache[2];
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 17fdf4b..fe24cec 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1289,8 +1289,18 @@
 				(flags & GPIOF_INIT_HIGH) ? 1 : 0);
 
 	if (err)
-		gpio_free(gpio);
+		goto free_gpio;
 
+	if (flags & GPIOF_EXPORT) {
+		err = gpio_export(gpio, flags & GPIOF_EXPORT_CHANGEABLE);
+		if (err)
+			goto free_gpio;
+	}
+
+	return 0;
+
+ free_gpio:
+	gpio_free(gpio);
 	return err;
 }
 EXPORT_SYMBOL_GPL(gpio_request_one);
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index a220e57..4748086 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -545,8 +545,7 @@
 	if (ret)
 		goto err_cleanup;
 
-	ret = request_irq(irq, vmbus_isr, IRQF_SAMPLE_RANDOM,
-			driver_name, hv_acpi_dev);
+	ret = request_irq(irq, vmbus_isr, 0, driver_name, hv_acpi_dev);
 
 	if (ret != 0) {
 		pr_err("Unable to request IRQ %d\n",
diff --git a/drivers/i2c/busses/i2c-pmcmsp.c b/drivers/i2c/busses/i2c-pmcmsp.c
index 07b7447..3d71395 100644
--- a/drivers/i2c/busses/i2c-pmcmsp.c
+++ b/drivers/i2c/busses/i2c-pmcmsp.c
@@ -306,8 +306,7 @@
 	pmcmsptwi_data.irq = platform_get_irq(pldev, 0);
 	if (pmcmsptwi_data.irq) {
 		rc = request_irq(pmcmsptwi_data.irq, &pmcmsptwi_interrupt,
-			IRQF_SHARED | IRQF_SAMPLE_RANDOM,
-			pldev->name, &pmcmsptwi_data);
+				 IRQF_SHARED, pldev->name, &pmcmsptwi_data);
 		if (rc == 0) {
 			/*
 			 * Enable 'DONE' interrupt only.
diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c
index be33160..1831636 100644
--- a/drivers/input/serio/hp_sdc.c
+++ b/drivers/input/serio/hp_sdc.c
@@ -879,7 +879,7 @@
 #endif
 
 	errstr = "IRQ not available for";
-	if (request_irq(hp_sdc.irq, &hp_sdc_isr, IRQF_SHARED|IRQF_SAMPLE_RANDOM,
+	if (request_irq(hp_sdc.irq, &hp_sdc_isr, IRQF_SHARED,
 			"HP SDC", &hp_sdc))
 		goto err1;
 
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 9ca28fc..d7e6b7f 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -480,4 +480,22 @@
 comment "iptables trigger is under Netfilter config (LED target)"
 	depends on LEDS_TRIGGERS
 
+config LEDS_TRIGGER_MORSE
+	tristate "LED Morse Trigger"
+	depends on LEDS_TRIGGERS
+
+config LEDS_TRIGGER_NETDEV
+	tristate "LED Netdev Trigger"
+	depends on NET && LEDS_TRIGGERS
+	help
+	  This allows LEDs to be controlled by network device activity.
+	  If unsure, say Y.
+
+config LEDS_TRIGGER_USBDEV
+	tristate "LED USB device Trigger"
+	depends on USB && LEDS_TRIGGERS
+	help
+	  This allows LEDs to be controlled by the presence/activity of
+	  an USB device. If unsure, say N.
+
 endif # NEW_LEDS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 1fc6875..3627c67 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -57,3 +57,6 @@
 obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT)	+= ledtrig-backlight.o
 obj-$(CONFIG_LEDS_TRIGGER_GPIO)		+= ledtrig-gpio.o
 obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON)	+= ledtrig-default-on.o
+obj-$(CONFIG_LEDS_TRIGGER_MORSE)	+= ledtrig-morse.o
+obj-$(CONFIG_LEDS_TRIGGER_NETDEV)	+= ledtrig-netdev.o
+obj-$(CONFIG_LEDS_TRIGGER_USBDEV)	+= ledtrig-usbdev.o
diff --git a/drivers/leds/ledtrig-morse.c b/drivers/leds/ledtrig-morse.c
index bc58afe..efa78c8 100644
--- a/drivers/leds/ledtrig-morse.c
+++ b/drivers/leds/ledtrig-morse.c
@@ -26,7 +26,6 @@
 #include <linux/list.h>
 #include <linux/spinlock.h>
 #include <linux/device.h>
-#include <linux/sysdev.h>
 #include <linux/timer.h>
 #include <linux/ctype.h>
 #include <linux/leds.h>
diff --git a/drivers/leds/ledtrig-netdev.c b/drivers/leds/ledtrig-netdev.c
index 6c56acb..72a8cd8 100644
--- a/drivers/leds/ledtrig-netdev.c
+++ b/drivers/leds/ledtrig-netdev.c
@@ -22,7 +22,6 @@
 #include <linux/list.h>
 #include <linux/spinlock.h>
 #include <linux/device.h>
-#include <linux/sysdev.h>
 #include <linux/netdevice.h>
 #include <linux/timer.h>
 #include <linux/ctype.h>
@@ -307,8 +306,9 @@
 static void netdev_trig_timer(unsigned long arg)
 {
 	struct led_netdev_data *trigger_data = (struct led_netdev_data *)arg;
-	const struct net_device_stats *dev_stats;
+	struct rtnl_link_stats64 *dev_stats;
 	unsigned new_activity;
+	struct rtnl_link_stats64 temp;
 
 	write_lock(&trigger_data->lock);
 
@@ -318,7 +318,7 @@
 		goto no_restart;
 	}
 
-	dev_stats = dev_get_stats(trigger_data->net_dev);
+	dev_stats = dev_get_stats(trigger_data->net_dev, &temp);
 	new_activity =
 		((trigger_data->mode & MODE_TX) ? dev_stats->tx_packets : 0) +
 		((trigger_data->mode & MODE_RX) ? dev_stats->rx_packets : 0);
diff --git a/drivers/leds/ledtrig-usbdev.c b/drivers/leds/ledtrig-usbdev.c
index 70b0e39..0309aa4 100644
--- a/drivers/leds/ledtrig-usbdev.c
+++ b/drivers/leds/ledtrig-usbdev.c
@@ -24,7 +24,6 @@
 #include <linux/list.h>
 #include <linux/spinlock.h>
 #include <linux/device.h>
-#include <linux/sysdev.h>
 #include <linux/timer.h>
 #include <linux/ctype.h>
 #include <linux/slab.h>
diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c
index 60107ee..f468a4e 100644
--- a/drivers/mfd/ab3100-core.c
+++ b/drivers/mfd/ab3100-core.c
@@ -409,8 +409,6 @@
 	u32 fatevent;
 	int err;
 
-	add_interrupt_randomness(irq);
-
 	err = ab3100_get_register_page_interruptible(ab3100, AB3100_EVENTA1,
 				       event_regs, 3);
 	if (err)
@@ -939,9 +937,6 @@
 
 	err = request_threaded_irq(client->irq, NULL, ab3100_irq_handler,
 				IRQF_ONESHOT, "ab3100-core", ab3100);
-	/* This real unpredictable IRQ is of course sampled for entropy */
-	rand_initialize_irq(client->irq);
-
 	if (err)
 		goto exit_no_irq;
 
diff --git a/drivers/mfd/tps65010.c b/drivers/mfd/tps65010.c
index 93d5fdf..775943e 100644
--- a/drivers/mfd/tps65010.c
+++ b/drivers/mfd/tps65010.c
@@ -563,8 +563,7 @@
 	 */
 	if (client->irq > 0) {
 		status = request_irq(client->irq, tps65010_irq,
-			IRQF_SAMPLE_RANDOM | IRQF_TRIGGER_FALLING,
-			DRIVER_NAME, tps);
+			IRQF_TRIGGER_FALLING, DRIVER_NAME, tps);
 		if (status < 0) {
 			dev_dbg(&client->dev, "can't get IRQ %d, err %d\n",
 					client->irq, status);
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 00fcbed..c68b6d8 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -474,6 +474,31 @@
 	  This provides support for the SDHI SD/SDIO controller found in
 	  SuperH and ARM SH-Mobile SoCs
 
+config GPIOMMC
+	tristate "MMC/SD over GPIO-based SPI"
+	depends on MMC && MMC_SPI && SPI_GPIO_OLD
+	help
+	  This driver hooks up the mmc_spi and spi_gpio modules so that
+	  MMC/SD cards can be used on a GPIO based bus by bitbanging
+	  the SPI protocol in software.
+
+	  This driver provides a configfs interface to dynamically create
+	  and destroy GPIO-based MMC/SD card devices. It also provides
+	  a platform device interface API.
+	  See Documentation/gpiommc.txt for details.
+
+	  The module will be called gpiommc.
+
+	  If unsure, say N.
+
+config GPIOMMC_CONFIGFS
+	bool
+	depends on GPIOMMC && CONFIGFS_FS
+	default y
+	help
+	  This option automatically enables configfs support for gpiommc
+	  if configfs is available.
+
 config MMC_CB710
 	tristate "ENE CB710 MMC/SD Interface support"
 	depends on PCI
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index 745f8fc..aee80d9 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -37,6 +37,7 @@
 obj-$(CONFIG_MMC_SDHI)		+= sh_mobile_sdhi.o
 obj-$(CONFIG_MMC_CB710)		+= cb710-mmc.o
 obj-$(CONFIG_MMC_VIA_SDMMC)	+= via-sdmmc.o
+obj-$(CONFIG_GPIOMMC)		+= gpiommc.o
 obj-$(CONFIG_SDH_BFIN)		+= bfin_sdh.o
 obj-$(CONFIG_MMC_DW)		+= dw_mmc.o
 obj-$(CONFIG_MMC_SH_MMCIF)	+= sh_mmcif.o
diff --git a/drivers/mmc/host/gpiommc.c b/drivers/mmc/host/gpiommc.c
new file mode 100644
index 0000000..7a0e2ee
--- /dev/null
+++ b/drivers/mmc/host/gpiommc.c
@@ -0,0 +1,620 @@
+/*
+ * Driver an MMC/SD card on a bitbanging GPIO SPI bus.
+ * This module hooks up the mmc_spi and spi_gpio modules and also
+ * provides a configfs interface.
+ *
+ * Copyright 2008 Michael Buesch <mb@bu3sch.de>
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+#include <linux/module.h>
+#include <linux/mmc/gpiommc.h>
+#include <linux/platform_device.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/spi/spi_gpio_old.h>
+#include <linux/configfs.h>
+#include <linux/gpio.h>
+#include <asm/atomic.h>
+
+
+#define PFX				"gpio-mmc: "
+
+
+struct gpiommc_device {
+	struct platform_device *pdev;
+	struct platform_device *spi_pdev;
+	struct spi_board_info boardinfo;
+};
+
+
+MODULE_DESCRIPTION("GPIO based MMC driver");
+MODULE_AUTHOR("Michael Buesch");
+MODULE_LICENSE("GPL");
+
+
+static int gpiommc_boardinfo_setup(struct spi_board_info *bi,
+				   struct spi_master *master,
+				   void *data)
+{
+	struct gpiommc_device *d = data;
+	struct gpiommc_platform_data *pdata = d->pdev->dev.platform_data;
+
+	/* Bind the SPI master to the MMC-SPI host driver. */
+	strlcpy(bi->modalias, "mmc_spi", sizeof(bi->modalias));
+
+	bi->max_speed_hz = pdata->max_bus_speed;
+	bi->bus_num = master->bus_num;
+	bi->mode = pdata->mode;
+
+	return 0;
+}
+
+static int gpiommc_probe(struct platform_device *pdev)
+{
+	struct gpiommc_platform_data *mmc_pdata = pdev->dev.platform_data;
+	struct spi_gpio_platform_data spi_pdata;
+	struct gpiommc_device *d;
+	int err;
+
+	err = -ENXIO;
+	if (!mmc_pdata)
+		goto error;
+
+#ifdef CONFIG_MMC_SPI_MODULE
+	err = request_module("mmc_spi");
+	if (err) {
+		printk(KERN_WARNING PFX
+		       "Failed to request mmc_spi module.\n");
+	}
+#endif /* CONFIG_MMC_SPI_MODULE */
+
+	/* Allocate the GPIO-MMC device */
+	err = -ENOMEM;
+	d = kzalloc(sizeof(*d), GFP_KERNEL);
+	if (!d)
+		goto error;
+	d->pdev = pdev;
+
+	/* Create the SPI-GPIO device */
+	d->spi_pdev = platform_device_alloc(SPI_GPIO_PLATDEV_NAME,
+					    spi_gpio_next_id());
+	if (!d->spi_pdev)
+		goto err_free_d;
+
+	memset(&spi_pdata, 0, sizeof(spi_pdata));
+	spi_pdata.pin_clk = mmc_pdata->pins.gpio_clk;
+	spi_pdata.pin_miso = mmc_pdata->pins.gpio_do;
+	spi_pdata.pin_mosi = mmc_pdata->pins.gpio_di;
+	spi_pdata.pin_cs = mmc_pdata->pins.gpio_cs;
+	spi_pdata.cs_activelow = mmc_pdata->pins.cs_activelow;
+	spi_pdata.no_spi_delay = mmc_pdata->no_spi_delay;
+	spi_pdata.boardinfo_setup = gpiommc_boardinfo_setup;
+	spi_pdata.boardinfo_setup_data = d;
+
+	err = platform_device_add_data(d->spi_pdev, &spi_pdata,
+				       sizeof(spi_pdata));
+	if (err)
+		goto err_free_pdev;
+	err = platform_device_add(d->spi_pdev);
+	if (err)
+		goto err_free_pdata;
+	platform_set_drvdata(pdev, d);
+
+	printk(KERN_INFO PFX "MMC-Card \"%s\" "
+	       "attached to GPIO pins di=%u, do=%u, clk=%u, cs=%u\n",
+	       mmc_pdata->name, mmc_pdata->pins.gpio_di,
+	       mmc_pdata->pins.gpio_do,
+	       mmc_pdata->pins.gpio_clk,
+	       mmc_pdata->pins.gpio_cs);
+
+	return 0;
+
+err_free_pdata:
+	kfree(d->spi_pdev->dev.platform_data);
+	d->spi_pdev->dev.platform_data = NULL;
+err_free_pdev:
+	platform_device_put(d->spi_pdev);
+err_free_d:
+	kfree(d);
+error:
+	return err;
+}
+
+static int gpiommc_remove(struct platform_device *pdev)
+{
+	struct gpiommc_device *d = platform_get_drvdata(pdev);
+	struct gpiommc_platform_data *pdata = d->pdev->dev.platform_data;
+
+	platform_device_unregister(d->spi_pdev);
+	printk(KERN_INFO PFX "GPIO based MMC-Card \"%s\" removed\n",
+	       pdata->name);
+	platform_device_put(d->spi_pdev);
+
+	return 0;
+}
+
+#ifdef CONFIG_GPIOMMC_CONFIGFS
+
+/* A device that was created through configfs */
+struct gpiommc_configfs_device {
+	struct config_item item;
+	/* The platform device, after registration. */
+	struct platform_device *pdev;
+	/* The configuration */
+	struct gpiommc_platform_data pdata;
+	/* Mutex to protect this structure */
+	struct mutex mutex;
+};
+
+#define GPIO_INVALID	-1
+
+static inline bool gpiommc_is_registered(struct gpiommc_configfs_device *dev)
+{
+	return (dev->pdev != NULL);
+}
+
+static inline struct gpiommc_configfs_device *ci_to_gpiommc(struct config_item *item)
+{
+	return item ? container_of(item, struct gpiommc_configfs_device, item) : NULL;
+}
+
+static struct configfs_attribute gpiommc_attr_DI = {
+	.ca_owner = THIS_MODULE,
+	.ca_name = "gpio_data_in",
+	.ca_mode = S_IRUGO | S_IWUSR,
+};
+
+static struct configfs_attribute gpiommc_attr_DO = {
+	.ca_owner = THIS_MODULE,
+	.ca_name = "gpio_data_out",
+	.ca_mode = S_IRUGO | S_IWUSR,
+};
+
+static struct configfs_attribute gpiommc_attr_CLK = {
+	.ca_owner = THIS_MODULE,
+	.ca_name = "gpio_clock",
+	.ca_mode = S_IRUGO | S_IWUSR,
+};
+
+static struct configfs_attribute gpiommc_attr_CS = {
+	.ca_owner = THIS_MODULE,
+	.ca_name = "gpio_chipselect",
+	.ca_mode = S_IRUGO | S_IWUSR,
+};
+
+static struct configfs_attribute gpiommc_attr_CS_activelow = {
+	.ca_owner = THIS_MODULE,
+	.ca_name = "gpio_chipselect_activelow",
+	.ca_mode = S_IRUGO | S_IWUSR,
+};
+
+static struct configfs_attribute gpiommc_attr_spimode = {
+	.ca_owner = THIS_MODULE,
+	.ca_name = "spi_mode",
+	.ca_mode = S_IRUGO | S_IWUSR,
+};
+
+static struct configfs_attribute gpiommc_attr_spidelay = {
+	.ca_owner = THIS_MODULE,
+	.ca_name = "spi_delay",
+	.ca_mode = S_IRUGO | S_IWUSR,
+};
+
+static struct configfs_attribute gpiommc_attr_max_bus_speed = {
+	.ca_owner = THIS_MODULE,
+	.ca_name = "max_bus_speed",
+	.ca_mode = S_IRUGO | S_IWUSR,
+};
+
+static struct configfs_attribute gpiommc_attr_register = {
+	.ca_owner = THIS_MODULE,
+	.ca_name = "register",
+	.ca_mode = S_IRUGO | S_IWUSR,
+};
+
+static struct configfs_attribute *gpiommc_config_attrs[] = {
+	&gpiommc_attr_DI,
+	&gpiommc_attr_DO,
+	&gpiommc_attr_CLK,
+	&gpiommc_attr_CS,
+	&gpiommc_attr_CS_activelow,
+	&gpiommc_attr_spimode,
+	&gpiommc_attr_spidelay,
+	&gpiommc_attr_max_bus_speed,
+	&gpiommc_attr_register,
+	NULL,
+};
+
+static ssize_t gpiommc_config_attr_show(struct config_item *item,
+					struct configfs_attribute *attr,
+					char *page)
+{
+	struct gpiommc_configfs_device *dev = ci_to_gpiommc(item);
+	ssize_t count = 0;
+	unsigned int gpio;
+	int err = 0;
+
+	mutex_lock(&dev->mutex);
+
+	if (attr == &gpiommc_attr_DI) {
+		gpio = dev->pdata.pins.gpio_di;
+		if (gpio == GPIO_INVALID)
+			count = snprintf(page, PAGE_SIZE, "not configured\n");
+		else
+			count = snprintf(page, PAGE_SIZE, "%u\n", gpio);
+		goto out;
+	}
+	if (attr == &gpiommc_attr_DO) {
+		gpio = dev->pdata.pins.gpio_do;
+		if (gpio == GPIO_INVALID)
+			count = snprintf(page, PAGE_SIZE, "not configured\n");
+		else
+			count = snprintf(page, PAGE_SIZE, "%u\n", gpio);
+		goto out;
+	}
+	if (attr == &gpiommc_attr_CLK) {
+		gpio = dev->pdata.pins.gpio_clk;
+		if (gpio == GPIO_INVALID)
+			count = snprintf(page, PAGE_SIZE, "not configured\n");
+		else
+			count = snprintf(page, PAGE_SIZE, "%u\n", gpio);
+		goto out;
+	}
+	if (attr == &gpiommc_attr_CS) {
+		gpio = dev->pdata.pins.gpio_cs;
+		if (gpio == GPIO_INVALID)
+			count = snprintf(page, PAGE_SIZE, "not configured\n");
+		else
+			count = snprintf(page, PAGE_SIZE, "%u\n", gpio);
+		goto out;
+	}
+	if (attr == &gpiommc_attr_CS_activelow) {
+		count = snprintf(page, PAGE_SIZE, "%u\n",
+				 dev->pdata.pins.cs_activelow);
+		goto out;
+	}
+	if (attr == &gpiommc_attr_spimode) {
+		count = snprintf(page, PAGE_SIZE, "%u\n",
+				 dev->pdata.mode);
+		goto out;
+	}
+	if (attr == &gpiommc_attr_spidelay) {
+		count = snprintf(page, PAGE_SIZE, "%u\n",
+				 !dev->pdata.no_spi_delay);
+		goto out;
+	}
+	if (attr == &gpiommc_attr_max_bus_speed) {
+		count = snprintf(page, PAGE_SIZE, "%u\n",
+				 dev->pdata.max_bus_speed);
+		goto out;
+	}
+	if (attr == &gpiommc_attr_register) {
+		count = snprintf(page, PAGE_SIZE, "%u\n",
+				 gpiommc_is_registered(dev));
+		goto out;
+	}
+	WARN_ON(1);
+	err = -ENOSYS;
+out:
+	mutex_unlock(&dev->mutex);
+
+	return err ? err : count;
+}
+
+static int gpiommc_do_register(struct gpiommc_configfs_device *dev,
+			       const char *name)
+{
+	int err;
+
+	if (gpiommc_is_registered(dev))
+		return 0;
+
+	if (!gpio_is_valid(dev->pdata.pins.gpio_di) ||
+	    !gpio_is_valid(dev->pdata.pins.gpio_do) ||
+	    !gpio_is_valid(dev->pdata.pins.gpio_clk) ||
+	    !gpio_is_valid(dev->pdata.pins.gpio_cs)) {
+		printk(KERN_ERR PFX
+		       "configfs: Invalid GPIO pin number(s)\n");
+		return -EINVAL;
+	}
+
+	strlcpy(dev->pdata.name, name,
+		sizeof(dev->pdata.name));
+
+	dev->pdev = platform_device_alloc(GPIOMMC_PLATDEV_NAME,
+					  gpiommc_next_id());
+	if (!dev->pdev)
+		return -ENOMEM;
+	err = platform_device_add_data(dev->pdev, &dev->pdata,
+				       sizeof(dev->pdata));
+	if (err) {
+		platform_device_put(dev->pdev);
+		return err;
+	}
+	err = platform_device_add(dev->pdev);
+	if (err) {
+		platform_device_put(dev->pdev);
+		return err;
+	}
+
+	return 0;
+}
+
+static void gpiommc_do_unregister(struct gpiommc_configfs_device *dev)
+{
+	if (!gpiommc_is_registered(dev))
+		return;
+
+	platform_device_unregister(dev->pdev);
+	dev->pdev = NULL;
+}
+
+static ssize_t gpiommc_config_attr_store(struct config_item *item,
+					 struct configfs_attribute *attr,
+					 const char *page, size_t count)
+{
+	struct gpiommc_configfs_device *dev = ci_to_gpiommc(item);
+	int err = -EINVAL;
+	unsigned long data;
+
+	mutex_lock(&dev->mutex);
+
+	if (attr == &gpiommc_attr_register) {
+		err = strict_strtoul(page, 10, &data);
+		if (err)
+			goto out;
+		err = -EINVAL;
+		if (data == 1)
+			err = gpiommc_do_register(dev, item->ci_name);
+		if (data == 0) {
+			gpiommc_do_unregister(dev);
+			err = 0;
+		}
+		goto out;
+	}
+
+	if (gpiommc_is_registered(dev)) {
+		/* The rest of the config parameters can only be set
+		 * as long as the device is not registered, yet. */
+		err = -EBUSY;
+		goto out;
+	}
+
+	if (attr == &gpiommc_attr_DI) {
+		err = strict_strtoul(page, 10, &data);
+		if (err)
+			goto out;
+		err = -EINVAL;
+		if (!gpio_is_valid(data))
+			goto out;
+		dev->pdata.pins.gpio_di = data;
+		err = 0;
+		goto out;
+	}
+	if (attr == &gpiommc_attr_DO) {
+		err = strict_strtoul(page, 10, &data);
+		if (err)
+			goto out;
+		err = -EINVAL;
+		if (!gpio_is_valid(data))
+			goto out;
+		dev->pdata.pins.gpio_do = data;
+		err = 0;
+		goto out;
+	}
+	if (attr == &gpiommc_attr_CLK) {
+		err = strict_strtoul(page, 10, &data);
+		if (err)
+			goto out;
+		err = -EINVAL;
+		if (!gpio_is_valid(data))
+			goto out;
+		dev->pdata.pins.gpio_clk = data;
+		err = 0;
+		goto out;
+	}
+	if (attr == &gpiommc_attr_CS) {
+		err = strict_strtoul(page, 10, &data);
+		if (err)
+			goto out;
+		err = -EINVAL;
+		if (!gpio_is_valid(data))
+			goto out;
+		dev->pdata.pins.gpio_cs = data;
+		err = 0;
+		goto out;
+	}
+	if (attr == &gpiommc_attr_CS_activelow) {
+		err = strict_strtoul(page, 10, &data);
+		if (err)
+			goto out;
+		err = -EINVAL;
+		if (data != 0 && data != 1)
+			goto out;
+		dev->pdata.pins.cs_activelow = data;
+		err = 0;
+		goto out;
+	}
+	if (attr == &gpiommc_attr_spimode) {
+		err = strict_strtoul(page, 10, &data);
+		if (err)
+			goto out;
+		err = -EINVAL;
+		switch (data) {
+		case 0:
+			dev->pdata.mode = SPI_MODE_0;
+			break;
+		case 1:
+			dev->pdata.mode = SPI_MODE_1;
+			break;
+		case 2:
+			dev->pdata.mode = SPI_MODE_2;
+			break;
+		case 3:
+			dev->pdata.mode = SPI_MODE_3;
+			break;
+		default:
+			goto out;
+		}
+		err = 0;
+		goto out;
+	}
+	if (attr == &gpiommc_attr_spidelay) {
+		err = strict_strtoul(page, 10, &data);
+		if (err)
+			goto out;
+		err = -EINVAL;
+		if (data != 0 && data != 1)
+			goto out;
+		dev->pdata.no_spi_delay = !data;
+		err = 0;
+		goto out;
+	}
+	if (attr == &gpiommc_attr_max_bus_speed) {
+		err = strict_strtoul(page, 10, &data);
+		if (err)
+			goto out;
+		err = -EINVAL;
+		if (data > UINT_MAX)
+			goto out;
+		dev->pdata.max_bus_speed = data;
+		err = 0;
+		goto out;
+	}
+	WARN_ON(1);
+	err = -ENOSYS;
+out:
+	mutex_unlock(&dev->mutex);
+
+	return err ? err : count;
+}
+
+static void gpiommc_config_item_release(struct config_item *item)
+{
+	struct gpiommc_configfs_device *dev = ci_to_gpiommc(item);
+
+	kfree(dev);
+}
+
+static struct configfs_item_operations gpiommc_config_item_ops = {
+	.release		= gpiommc_config_item_release,
+	.show_attribute		= gpiommc_config_attr_show,
+	.store_attribute	= gpiommc_config_attr_store,
+};
+
+static struct config_item_type gpiommc_dev_ci_type = {
+	.ct_item_ops	= &gpiommc_config_item_ops,
+	.ct_attrs	= gpiommc_config_attrs,
+	.ct_owner	= THIS_MODULE,
+};
+
+static struct config_item *gpiommc_make_item(struct config_group *group,
+					     const char *name)
+{
+	struct gpiommc_configfs_device *dev;
+
+	if (strlen(name) > GPIOMMC_MAX_NAMELEN) {
+		printk(KERN_ERR PFX "configfs: device name too long\n");
+		return NULL;
+	}
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return NULL;
+
+	mutex_init(&dev->mutex);
+	config_item_init_type_name(&dev->item, name,
+				   &gpiommc_dev_ci_type);
+
+	/* Assign default configuration */
+	dev->pdata.pins.gpio_di = GPIO_INVALID;
+	dev->pdata.pins.gpio_do = GPIO_INVALID;
+	dev->pdata.pins.gpio_clk = GPIO_INVALID;
+	dev->pdata.pins.gpio_cs = GPIO_INVALID;
+	dev->pdata.pins.cs_activelow = 1;
+	dev->pdata.mode = SPI_MODE_0;
+	dev->pdata.no_spi_delay = 0;
+	dev->pdata.max_bus_speed = 5000000; /* 5 MHz */
+
+	return &(dev->item);
+}
+
+static void gpiommc_drop_item(struct config_group *group,
+			      struct config_item *item)
+{
+	struct gpiommc_configfs_device *dev = ci_to_gpiommc(item);
+
+	gpiommc_do_unregister(dev);
+	kfree(dev);
+}
+
+static struct configfs_group_operations gpiommc_ct_group_ops = {
+	.make_item	= gpiommc_make_item,
+	.drop_item	= gpiommc_drop_item,
+};
+
+static struct config_item_type gpiommc_ci_type = {
+	.ct_group_ops	= &gpiommc_ct_group_ops,
+	.ct_owner	= THIS_MODULE,
+};
+
+static struct configfs_subsystem gpiommc_subsys = {
+	.su_group = {
+		.cg_item = {
+			.ci_namebuf = GPIOMMC_PLATDEV_NAME,
+			.ci_type = &gpiommc_ci_type,
+		},
+	},
+	.su_mutex = __MUTEX_INITIALIZER(gpiommc_subsys.su_mutex),
+};
+
+#endif /* CONFIG_GPIOMMC_CONFIGFS */
+
+static struct platform_driver gpiommc_plat_driver = {
+	.probe	= gpiommc_probe,
+	.remove	= gpiommc_remove,
+	.driver	= {
+		.name	= GPIOMMC_PLATDEV_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+int gpiommc_next_id(void)
+{
+	static atomic_t counter = ATOMIC_INIT(-1);
+
+	return atomic_inc_return(&counter);
+}
+EXPORT_SYMBOL(gpiommc_next_id);
+
+static int __init gpiommc_modinit(void)
+{
+	int err;
+
+	err = platform_driver_register(&gpiommc_plat_driver);
+	if (err)
+		return err;
+
+#ifdef CONFIG_GPIOMMC_CONFIGFS
+	config_group_init(&gpiommc_subsys.su_group);
+	err = configfs_register_subsystem(&gpiommc_subsys);
+	if (err) {
+		platform_driver_unregister(&gpiommc_plat_driver);
+		return err;
+	}
+#endif /* CONFIG_GPIOMMC_CONFIGFS */
+
+	return 0;
+}
+module_init(gpiommc_modinit);
+
+static void __exit gpiommc_modexit(void)
+{
+#ifdef CONFIG_GPIOMMC_CONFIGFS
+	configfs_unregister_subsystem(&gpiommc_subsys);
+#endif
+	platform_driver_unregister(&gpiommc_plat_driver);
+}
+module_exit(gpiommc_modexit);
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index 1be6218..982a98b 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -23,6 +23,14 @@
 	  WARNING: some of the tests will ERASE entire MTD device which they
 	  test. Do not use these tests unless you really know what you do.
 
+config MTD_ROOTFS_ROOT_DEV
+	bool "Automatically set 'rootfs' partition to be root filesystem"
+	default y
+
+config MTD_ROOTFS_SPLIT
+	bool "Automatically split 'rootfs' partition for squashfs"
+	default y
+
 config MTD_REDBOOT_PARTS
 	tristate "RedBoot partition table parsing"
 	---help---
@@ -148,6 +156,22 @@
 	  This provides partions parsing for BCM63xx devices with CFE
 	  bootloaders.
 
+config MTD_MYLOADER_PARTS
+	tristate "MyLoader partition parsing"
+	depends on ADM5120 || ATHEROS_AR231X || ATHEROS_AR71XX || ATH79
+	---help---
+	  MyLoader is a bootloader which allows the user to define partitions
+	  in flash devices, by putting a table in the second erase block
+	  on the device, similar to a partition table. This table gives the 
+	  offsets and lengths of the user defined partitions.
+
+	  If you need code which can detect and parse these tables, and
+	  register MTD 'partitions' corresponding to each image detected,
+	  enable this option.
+
+	  You will still need the parsing functions to be called by the driver
+	  for your particular device. It won't happen automatically.
+
 comment "User Modules And Translation Layers"
 
 config MTD_CHAR
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
index f901354..cc0c225 100644
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -12,6 +12,7 @@
 obj-$(CONFIG_MTD_AFS_PARTS)	+= afs.o
 obj-$(CONFIG_MTD_AR7_PARTS)	+= ar7part.o
 obj-$(CONFIG_MTD_BCM63XX_PARTS)	+= bcm63xxpart.o
+obj-$(CONFIG_MTD_MYLOADER_PARTS) += myloader.o
 
 # 'Users' - code which presents functionality to userspace.
 obj-$(CONFIG_MTD_CHAR)		+= mtdchar.o
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index 8d70895..a4ceb01 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -682,7 +682,7 @@
 		return 0;
 
 	case FL_ERASING:
-		if (!cfip || !(cfip->EraseSuspend & (0x1|0x2)) ||
+		if (1 /* no suspend */ || !cfip || !(cfip->EraseSuspend & (0x1|0x2)) ||
 		    !(mode == FL_READY || mode == FL_POINT ||
 		    (mode == FL_WRITING && (cfip->EraseSuspend & 0x2))))
 			goto sleep;
@@ -1409,6 +1409,7 @@
 
 	/* Write Buffer Load */
 	map_write(map, CMD(0x25), cmd_adr);
+	(void) map_read(map, cmd_adr);
 
 	chip->state = FL_WRITING_TO_BUFFER;
 
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 37b05c3..8fc9201 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -102,6 +102,14 @@
 	help
 	  This option enables FAST_READ access supported by ST M25Pxx.
 
+config M25PXX_PREFER_SMALL_SECTOR_ERASE
+	bool "Prefer small sector erase"
+	depends on MTD_M25P80
+	default y
+	help
+	  This option enables use of the small erase sectors if that is
+	  supported by the flash chip.
+
 config MTD_SST25L
 	tristate "Support SST25L (non JEDEC) SPI Flash chips"
 	depends on SPI_MASTER
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
index 17f5517..3d996d3 100644
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -14,6 +14,7 @@
 #include <linux/list.h>
 #include <linux/init.h>
 #include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
 #include <linux/mutex.h>
 #include <linux/mount.h>
 #include <linux/slab.h>
@@ -28,6 +29,8 @@
 	struct block_device *blkdev;
 	struct mtd_info mtd;
 	struct mutex write_mutex;
+	rwlock_t bdev_mutex;
+	char devname[0];
 };
 
 
@@ -80,6 +83,12 @@
 	size_t len = instr->len;
 	int err;
 
+	read_lock(&dev->bdev_mutex);
+	if (!dev->blkdev) {
+		err = -EINVAL;
+		goto done;
+	}
+
 	instr->state = MTD_ERASING;
 	mutex_lock(&dev->write_mutex);
 	err = _block2mtd_erase(dev, from, len);
@@ -91,6 +100,10 @@
 		instr->state = MTD_ERASE_DONE;
 
 	mtd_erase_callback(instr);
+
+done:
+	read_unlock(&dev->bdev_mutex);
+
 	return err;
 }
 
@@ -102,10 +115,14 @@
 	struct page *page;
 	int index = from >> PAGE_SHIFT;
 	int offset = from & (PAGE_SIZE-1);
-	int cpylen;
+	int cpylen, err = 0;
 
-	if (from > mtd->size)
-		return -EINVAL;
+	read_lock(&dev->bdev_mutex);
+	if (!dev->blkdev || (from > mtd->size)) {
+		err = -EINVAL;
+		goto done;
+	}
+
 	if (from + len > mtd->size)
 		len = mtd->size - from;
 
@@ -120,10 +137,14 @@
 		len = len - cpylen;
 
 		page = page_read(dev->blkdev->bd_inode->i_mapping, index);
-		if (!page)
-			return -ENOMEM;
-		if (IS_ERR(page))
-			return PTR_ERR(page);
+		if (!page) {
+			err = -ENOMEM;
+			goto done;
+		}
+		if (IS_ERR(page)) {
+			err = PTR_ERR(page);
+			goto done;
+		}
 
 		memcpy(buf, page_address(page) + offset, cpylen);
 		page_cache_release(page);
@@ -134,7 +155,10 @@
 		offset = 0;
 		index++;
 	}
-	return 0;
+
+done:
+	read_unlock(&dev->bdev_mutex);
+	return err;
 }
 
 
@@ -186,12 +210,22 @@
 		size_t *retlen, const u_char *buf)
 {
 	struct block2mtd_dev *dev = mtd->priv;
-	int err;
+	int err = 0;
+
+	read_lock(&dev->bdev_mutex);
+	if (!dev->blkdev) {
+		err = -EINVAL;
+		goto done;
+	}
 
 	if (!len)
-		return 0;
-	if (to >= mtd->size)
-		return -ENOSPC;
+		goto done;
+
+	if (to >= mtd->size) {
+		err = -ENOSPC;
+		goto done;
+	}
+
 	if (to + len > mtd->size)
 		len = mtd->size - to;
 
@@ -200,6 +234,9 @@
 	mutex_unlock(&dev->write_mutex);
 	if (err > 0)
 		err = 0;
+
+done:
+	read_unlock(&dev->bdev_mutex);
 	return err;
 }
 
@@ -208,79 +245,142 @@
 static void block2mtd_sync(struct mtd_info *mtd)
 {
 	struct block2mtd_dev *dev = mtd->priv;
+	read_lock(&dev->bdev_mutex);
+	if (dev->blkdev)
 	sync_blockdev(dev->blkdev);
+	read_unlock(&dev->bdev_mutex);
+
 	return;
 }
 
 
+static int _open_bdev(struct block2mtd_dev *dev)
+{
+	const fmode_t mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL;
+	struct block_device *bdev;
+
+	/* Get a handle on the device */
+	bdev = blkdev_get_by_path(dev->devname, mode, dev);
+#ifndef MODULE
+	if (IS_ERR(bdev)) {
+		dev_t devt;
+
+		/* We might not have rootfs mounted at this point. Try
+		   to resolve the device name by other means. */
+
+		wait_for_device_probe();
+		devt = name_to_dev_t(dev->devname);
+		if (devt)
+			bdev = blkdev_get_by_dev(devt, mode, dev);
+	}
+#endif
+
+	if (IS_ERR(bdev)) {
+		ERROR("error: cannot open device %s", dev->devname);
+		return 1;
+	}
+	dev->blkdev = bdev;
+
+	if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) {
+		ERROR("attempting to use an MTD device as a block device");
+		return 1;
+	}
+
+	return 0;
+}
+
+static void _close_bdev(struct block2mtd_dev *dev)
+{
+	struct block_device *bdev;
+
+	if (!dev->blkdev)
+		return;
+
+	bdev = dev->blkdev;
+	invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping, 0, -1);
+	blkdev_put(dev->blkdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
+	dev->blkdev = NULL;
+}
+
 static void block2mtd_free_device(struct block2mtd_dev *dev)
 {
 	if (!dev)
 		return;
 
 	kfree(dev->mtd.name);
-
-	if (dev->blkdev) {
-		invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping,
-					0, -1);
-		blkdev_put(dev->blkdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
-	}
-
+	_close_bdev(dev);
 	kfree(dev);
 }
 
 
-/* FIXME: ensure that mtd->size % erase_size == 0 */
-static struct block2mtd_dev *add_device(char *devname, int erase_size)
+static int block2mtd_refresh(struct mtd_info *mtd)
 {
-	const fmode_t mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL;
+	struct block2mtd_dev *dev = mtd->priv;
 	struct block_device *bdev;
+	dev_t devt;
+	int err = 0;
+
+	/* no other mtd function can run at this point */
+	write_lock(&dev->bdev_mutex);
+
+	/* get the device number for the whole disk */
+	devt = MKDEV(MAJOR(dev->blkdev->bd_dev), 0);
+
+	/* close the old block device */
+	_close_bdev(dev);
+
+	/* open the whole disk, issue a partition rescan, then */
+	bdev = blkdev_get_by_dev(devt, FMODE_WRITE | FMODE_READ, mtd);
+	if (!bdev || !bdev->bd_disk)
+		err = -EINVAL;
+#ifndef CONFIG_MTD_BLOCK2MTD_MODULE
+	else
+		err = rescan_partitions(bdev->bd_disk, bdev);
+#endif
+	if (bdev)
+		blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
+
+	/* try to open the partition block device again */
+	_open_bdev(dev);
+	write_unlock(&dev->bdev_mutex);
+
+	return err;
+}
+
+/* FIXME: ensure that mtd->size % erase_size == 0 */
+static struct block2mtd_dev *add_device(char *devname, int erase_size, char *mtdname)
+{
 	struct block2mtd_dev *dev;
+	struct mtd_partition *part;
 	char *name;
 
 	if (!devname)
 		return NULL;
 
-	dev = kzalloc(sizeof(struct block2mtd_dev), GFP_KERNEL);
+	dev = kzalloc(sizeof(struct block2mtd_dev) + strlen(devname) + 1, GFP_KERNEL);
 	if (!dev)
 		return NULL;
 
-	/* Get a handle on the device */
-	bdev = blkdev_get_by_path(devname, mode, dev);
-#ifndef MODULE
-	if (IS_ERR(bdev)) {
+	strcpy(dev->devname, devname);
 
-		/* We might not have rootfs mounted at this point. Try
-		   to resolve the device name by other means. */
-
-		dev_t devt = name_to_dev_t(devname);
-		if (devt)
-			bdev = blkdev_get_by_dev(devt, mode, dev);
-	}
-#endif
-
-	if (IS_ERR(bdev)) {
-		ERROR("error: cannot open device %s", devname);
+	if (_open_bdev(dev))
 		goto devinit_err;
-	}
-	dev->blkdev = bdev;
-
-	if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) {
-		ERROR("attempting to use an MTD device as a block device");
-		goto devinit_err;
-	}
 
 	mutex_init(&dev->write_mutex);
+	rwlock_init(&dev->bdev_mutex);
 
 	/* Setup the MTD structure */
 	/* make the name contain the block device in */
-	name = kasprintf(GFP_KERNEL, "block2mtd: %s", devname);
+	if (!mtdname)
+		mtdname = devname;
+	name = kmalloc(strlen(mtdname) + 1, GFP_KERNEL);
 	if (!name)
 		goto devinit_err;
 
+	strcpy(name, mtdname);
 	dev->mtd.name = name;
 
-	dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK;
+	dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK & ~(erase_size - 1);
 	dev->mtd.erasesize = erase_size;
 	dev->mtd.writesize = 1;
 	dev->mtd.writebufsize = PAGE_SIZE;
@@ -288,20 +388,23 @@
 	dev->mtd.flags = MTD_CAP_RAM;
 	dev->mtd.erase = block2mtd_erase;
 	dev->mtd.write = block2mtd_write;
-	dev->mtd.writev = mtd_writev;
 	dev->mtd.sync = block2mtd_sync;
 	dev->mtd.read = block2mtd_read;
 	dev->mtd.priv = dev;
 	dev->mtd.owner = THIS_MODULE;
+	dev->mtd.refresh_device = block2mtd_refresh;
 
-	if (mtd_device_register(&dev->mtd, NULL, 0)) {
+	part = kzalloc(sizeof(struct mtd_partition), GFP_KERNEL);
+	part->name = name;
+	part->offset = 0;
+	part->size = dev->mtd.size;
+	if (mtd_device_register(&dev->mtd, part, 1)) {
 		/* Device didn't get added, so free the entry */
 		goto devinit_err;
 	}
 	list_add(&dev->list, &blkmtd_device_list);
 	INFO("mtd%d: [%s] erase_size = %dKiB [%d]", dev->mtd.index,
-			dev->mtd.name + strlen("block2mtd: "),
-			dev->mtd.erasesize >> 10, dev->mtd.erasesize);
+			mtdname, dev->mtd.erasesize >> 10, dev->mtd.erasesize);
 	return dev;
 
 devinit_err:
@@ -374,9 +477,9 @@
 
 static int block2mtd_setup2(const char *val)
 {
-	char buf[80 + 12]; /* 80 for device, 12 for erase size */
+	char buf[80 + 12 + 80]; /* 80 for device, 12 for erase size, 80 for name */
 	char *str = buf;
-	char *token[2];
+	char *token[3];
 	char *name;
 	size_t erase_size = PAGE_SIZE;
 	int i, ret;
@@ -387,7 +490,7 @@
 	strcpy(str, val);
 	kill_final_newline(str);
 
-	for (i = 0; i < 2; i++)
+	for (i = 0; i < 3; i++)
 		token[i] = strsep(&str, ",");
 
 	if (str)
@@ -406,8 +509,10 @@
 			parse_err("illegal erase size");
 		}
 	}
+	if (token[2] && (strlen(token[2]) + 1 > 80))
+		parse_err("mtd device name too long");
 
-	add_device(name, erase_size);
+	add_device(name, erase_size, token[2]);
 
 	return 0;
 }
@@ -441,7 +546,7 @@
 
 
 module_param_call(block2mtd, block2mtd_setup, NULL, NULL, 0200);
-MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,<erasesize>]\"");
+MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,<erasesize>[,<name>]]\"");
 
 static int __init block2mtd_init(void)
 {
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 94eef7d..e9ecd39 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -45,6 +45,7 @@
 #define	OPCODE_BE_4K		0x20	/* Erase 4KiB block */
 #define	OPCODE_BE_32K		0x52	/* Erase 32KiB block */
 #define	OPCODE_CHIP_ERASE	0xc7	/* Erase whole flash chip */
+#define	OPCODE_BE_4K_PMC	0xd7	/* Erase 4KiB block on PMC chips*/
 #define	OPCODE_SE		0xd8	/* Sector erase (usually 64KiB) */
 #define	OPCODE_RDID		0x9f	/* Read JEDEC ID */
 
@@ -83,6 +84,12 @@
 
 #define JEDEC_MFR(_jedec_id)	((_jedec_id) >> 16)
 
+#ifdef CONFIG_M25PXX_PREFER_SMALL_SECTOR_ERASE
+#define PREFER_SMALL_SECTOR_ERASE 1
+#else
+#define PREFER_SMALL_SECTOR_ERASE 0
+#endif
+
 /****************************************************************************/
 
 struct m25p {
@@ -625,6 +632,7 @@
 	u16		flags;
 #define	SECT_4K		0x01		/* OPCODE_BE_4K works uniformly */
 #define	M25P_NO_ERASE	0x02		/* No erase command needed */
+#define	SECT_4K_PMC	0x04		/* OPCODE_BE_4K_PMC works uniformly */
 };
 
 #define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags)	\
@@ -669,6 +677,7 @@
 	{ "en25p32", INFO(0x1c2016, 0, 64 * 1024,  64, 0) },
 	{ "en25q32b", INFO(0x1c3016, 0, 64 * 1024,  64, 0) },
 	{ "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) },
+	{ "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, SECT_4K) },
 
 	/* Intel/Numonyx -- xxxs33b */
 	{ "160s33b",  INFO(0x898911, 0, 64 * 1024,  32, 0) },
@@ -686,6 +695,10 @@
 	{ "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) },
 	{ "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
 
+	/* PMC -- pm25x "blocks" are 32K, sectors are 4K */
+	{ "pm25lv512", INFO(0, 0, 32 * 1024, 2, SECT_4K_PMC) },
+	{ "pm25lv010", INFO(0, 0, 32 * 1024, 4, SECT_4K_PMC) },
+
 	/* Spansion -- single (large) sector size only, at least
 	 * for the chips listed here (without boot sectors).
 	 */
@@ -759,6 +772,7 @@
 	{ "w25q32", INFO(0xef4016, 0, 64 * 1024,  64, SECT_4K) },
 	{ "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) },
 	{ "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) },
+	{ "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) },
 
 	/* Catalyst / On Semiconductor -- non-JEDEC */
 	{ "cat25c11", CAT25_INFO(  16, 8, 16, 1) },
@@ -918,9 +932,12 @@
 		flash->mtd.write = m25p80_write;
 
 	/* prefer "small sector" erase if possible */
-	if (info->flags & SECT_4K) {
+	if (PREFER_SMALL_SECTOR_ERASE && (info->flags & SECT_4K)) {
 		flash->erase_opcode = OPCODE_BE_4K;
 		flash->mtd.erasesize = 4096;
+	} else if (info->flags & SECT_4K_PMC) {
+		flash->erase_opcode = OPCODE_BE_4K_PMC;
+		flash->mtd.erasesize = 4096;
 	} else {
 		flash->erase_opcode = OPCODE_SE;
 		flash->mtd.erasesize = info->sector_size;
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 853744d..ffb9bb0 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -1005,6 +1005,12 @@
 		break;
 	}
 
+	case MTDREFRESH:
+	{
+		ret = mtd_device_refresh(mtd);
+		break;
+	}
+
 	default:
 		ret = -ENOTTY;
 	}
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index a3d44c3..bad77da 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -4,6 +4,7 @@
  * Copyright © 2000 Nicolas Pitre <nico@fluxnic.net>
  * Copyright © 2002 Thomas Gleixner <gleixner@linutronix.de>
  * Copyright © 2000-2010 David Woodhouse <dwmw2@infradead.org>
+ * Copyright (c) 2013 The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -29,10 +30,16 @@
 #include <linux/kmod.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
+#include <linux/root_dev.h>
+#include <linux/magic.h>
 #include <linux/err.h>
 
 #include "mtdcore.h"
 
+static bool rootfs_split = 1;
+
+#define MTD_ERASE_PARTIAL	0x8000 /* partition only covers parts of an erase block */
+
 /* Our partition linked list */
 static LIST_HEAD(mtd_partitions);
 static DEFINE_MUTEX(mtd_partitions_mutex);
@@ -50,7 +57,7 @@
  * the pointer to that structure with this macro.
  */
 #define PART(x)  ((struct mtd_part *)(x))
-
+#define IS_PART(mtd) (mtd->read == part_read)
 
 /*
  * MTD methods which simply translate the effective address and pass through
@@ -250,13 +257,60 @@
 		return -EROFS;
 	if (instr->addr >= mtd->size)
 		return -EINVAL;
+
+	instr->partial_start = false;
+	if (mtd->flags & MTD_ERASE_PARTIAL) {
+		size_t readlen = 0;
+		u64 mtd_ofs;
+
+		instr->erase_buf = kmalloc(part->master->erasesize, GFP_ATOMIC);
+		if (!instr->erase_buf)
+			return -ENOMEM;
+
+		mtd_ofs = part->offset + instr->addr;
+		instr->erase_buf_ofs = do_div(mtd_ofs, part->master->erasesize);
+
+		if (instr->erase_buf_ofs > 0) {
+			instr->addr -= instr->erase_buf_ofs;
+			ret = mtd_read(part->master,
+				instr->addr + part->offset,
+				part->master->erasesize,
+				&readlen, instr->erase_buf);
+
+			instr->partial_start = true;
+		} else {
+			mtd_ofs = part->offset + part->mtd.size;
+			instr->erase_buf_ofs = part->master->erasesize -
+				do_div(mtd_ofs, part->master->erasesize);
+
+			if (instr->erase_buf_ofs > 0) {
+				instr->len += instr->erase_buf_ofs;
+				ret = mtd_read(part->master,
+					part->offset + instr->addr +
+					instr->len - part->master->erasesize,
+					part->master->erasesize, &readlen,
+					instr->erase_buf);
+			} else {
+				ret = 0;
+			}
+		}
+		if (ret < 0) {
+			kfree(instr->erase_buf);
+			return ret;
+		}
+
+	}
+
 	instr->addr += part->offset;
 	ret = mtd_erase(part->master, instr);
 	if (ret) {
 		if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
 			instr->fail_addr -= part->offset;
 		instr->addr -= part->offset;
+		if (mtd->flags & MTD_ERASE_PARTIAL)
+			kfree(instr->erase_buf);
 	}
+
 	return ret;
 }
 
@@ -264,7 +318,25 @@
 {
 	if (instr->mtd->erase == part_erase) {
 		struct mtd_part *part = PART(instr->mtd);
+		size_t wrlen = 0;
 
+		if (instr->mtd->flags & MTD_ERASE_PARTIAL) {
+			if (instr->partial_start) {
+				part->master->write(part->master,
+					instr->addr, instr->erase_buf_ofs,
+					&wrlen, instr->erase_buf);
+				instr->addr += instr->erase_buf_ofs;
+			} else {
+				instr->len -= instr->erase_buf_ofs;
+				part->master->write(part->master,
+					instr->addr + instr->len,
+					instr->erase_buf_ofs, &wrlen,
+					instr->erase_buf +
+					part->master->erasesize -
+					instr->erase_buf_ofs);
+			}
+			kfree(instr->erase_buf);
+		}
 		if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
 			instr->fail_addr -= part->offset;
 		instr->addr -= part->offset;
@@ -287,7 +359,14 @@
 	struct mtd_part *part = PART(mtd);
 	if ((len + ofs) > mtd->size)
 		return -EINVAL;
-	return mtd_unlock(part->master, ofs + part->offset, len);
+
+	ofs += part->offset;
+	if (mtd->flags & MTD_ERASE_PARTIAL) {
+		/* round up len to next erasesize and round down offset to prev block */
+		len = (mtd_div_by_eb(len, part->master) + 1) * part->master->erasesize;
+		ofs &= ~(part->master->erasesize - 1);
+	}
+	return mtd_unlock(part->master, ofs, len);
 }
 
 static int part_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
@@ -535,18 +614,24 @@
 	if ((slave->mtd.flags & MTD_WRITEABLE) &&
 	    mtd_mod_by_eb(slave->offset, &slave->mtd)) {
 		/* Doesn't start on a boundary of major erase size */
-		/* FIXME: Let it be writable if it is on a boundary of
-		 * _minor_ erase size though */
-		slave->mtd.flags &= ~MTD_WRITEABLE;
-		printk(KERN_WARNING"mtd: partition \"%s\" doesn't start on an erase block boundary -- force read-only\n",
-			part->name);
+		slave->mtd.flags |= MTD_ERASE_PARTIAL;
+		if (((u32) slave->mtd.size) > master->erasesize)
+			slave->mtd.flags &= ~MTD_WRITEABLE;
+		else
+			slave->mtd.erasesize = slave->mtd.size;
 	}
 	if ((slave->mtd.flags & MTD_WRITEABLE) &&
-	    mtd_mod_by_eb(slave->mtd.size, &slave->mtd)) {
-		slave->mtd.flags &= ~MTD_WRITEABLE;
-		printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase block -- force read-only\n",
-			part->name);
+	    mtd_mod_by_eb(slave->offset + slave->mtd.size, &slave->mtd)) {
+		slave->mtd.flags |= MTD_ERASE_PARTIAL;
+
+		if ((u32) slave->mtd.size > master->erasesize)
+			slave->mtd.flags &= ~MTD_WRITEABLE;
+		else
+			slave->mtd.erasesize = slave->mtd.size;
 	}
+	if ((slave->mtd.flags & (MTD_ERASE_PARTIAL|MTD_WRITEABLE)) == MTD_ERASE_PARTIAL)
+		printk(KERN_WARNING"mtd: partition \"%s\" must either start or end on erase block boundary or be smaller than an erase block -- forcing read-only\n",
+				part->name);
 
 	slave->mtd.ecclayout = master->ecclayout;
 	if (master->block_isbad) {
@@ -643,6 +728,164 @@
 }
 EXPORT_SYMBOL_GPL(mtd_del_partition);
 
+#ifdef CONFIG_MTD_ROOTFS_SPLIT
+#define ROOTFS_SPLIT_NAME "rootfs_data"
+#define ROOTFS_REMOVED_NAME "<removed>"
+
+struct squashfs_super_block {
+	__le32 s_magic;
+	__le32 pad0[9];
+	__le64 bytes_used;
+};
+
+
+static int split_squashfs(struct mtd_info *master, int offset, int *split_offset)
+{
+	struct squashfs_super_block sb;
+	int len, ret;
+
+	ret = master->read(master, offset, sizeof(sb), &len, (void *) &sb);
+	if (ret || (len != sizeof(sb))) {
+		printk(KERN_ALERT "split_squashfs: error occured while reading "
+			"from \"%s\"\n", master->name);
+		return -EINVAL;
+	}
+
+	if (SQUASHFS_MAGIC != le32_to_cpu(sb.s_magic) ) {
+		printk(KERN_ALERT "split_squashfs: no squashfs found in \"%s\"\n",
+			master->name);
+		*split_offset = 0;
+		return 0;
+	}
+
+	if (le64_to_cpu((sb.bytes_used)) <= 0) {
+		printk(KERN_ALERT "split_squashfs: squashfs is empty in \"%s\"\n",
+			master->name);
+		*split_offset = 0;
+		return 0;
+	}
+
+	len = (u32) le64_to_cpu(sb.bytes_used);
+	len += (offset & 0x000fffff);
+	len +=  (master->erasesize - 1);
+	len &= ~(master->erasesize - 1);
+	len -= (offset & 0x000fffff);
+	*split_offset = offset + len;
+
+	return 0;
+}
+
+static int split_rootfs_data(struct mtd_info *master, struct mtd_info *rpart, const struct mtd_partition *part)
+{
+	struct mtd_partition *dpart;
+	struct mtd_part *slave = NULL;
+	struct mtd_part *spart;
+	int ret, split_offset = 0;
+
+	spart = PART(rpart);
+	ret = split_squashfs(master, spart->offset, &split_offset);
+	if (ret)
+		return ret;
+
+	if (split_offset <= 0)
+		return 0;
+
+	dpart = kmalloc(sizeof(*part)+sizeof(ROOTFS_SPLIT_NAME)+1, GFP_KERNEL);
+	if (dpart == NULL) {
+		printk(KERN_INFO "split_squashfs: no memory for partition \"%s\"\n",
+			ROOTFS_SPLIT_NAME);
+		return -ENOMEM;
+	}
+
+	memcpy(dpart, part, sizeof(*part));
+	dpart->name = (unsigned char *)&dpart[1];
+	strcpy(dpart->name, ROOTFS_SPLIT_NAME);
+
+	dpart->size = rpart->size - (split_offset - spart->offset);
+	dpart->offset = split_offset;
+
+	if (dpart == NULL)
+		return 1;
+
+	printk(KERN_INFO "mtd: partition \"%s\" created automatically, ofs=%llX, len=%llX \n",
+		ROOTFS_SPLIT_NAME, dpart->offset, dpart->size);
+
+	slave = allocate_partition(master, dpart, 0, split_offset);
+	if (IS_ERR(slave))
+		return PTR_ERR(slave);
+	mutex_lock(&mtd_partitions_mutex);
+	list_add(&slave->list, &mtd_partitions);
+	mutex_unlock(&mtd_partitions_mutex);
+
+	add_mtd_device(&slave->mtd);
+
+	rpart->split = &slave->mtd;
+
+	return 0;
+}
+
+static int refresh_rootfs_split(struct mtd_info *mtd)
+{
+	struct mtd_partition tpart;
+	struct mtd_part *part;
+	char *name;
+	//int index = 0;
+	int offset, size;
+	int ret;
+
+	part = PART(mtd);
+
+	/* check for the new squashfs offset first */
+	ret = split_squashfs(part->master, part->offset, &offset);
+	if (ret)
+		return ret;
+
+	if ((offset > 0) && !mtd->split) {
+		printk(KERN_INFO "%s: creating new split partition for \"%s\"\n", __func__, mtd->name);
+		/* if we don't have a rootfs split partition, create a new one */
+		tpart.name = (char *) mtd->name;
+		tpart.size = mtd->size;
+		tpart.offset = part->offset;
+
+		return split_rootfs_data(part->master, &part->mtd, &tpart);
+	} else if ((offset > 0) && mtd->split) {
+		/* update the offsets of the existing partition */
+		size = mtd->size + part->offset - offset;
+
+		part = PART(mtd->split);
+		part->offset = offset;
+		part->mtd.size = size;
+		printk(KERN_INFO "%s: %s partition \"" ROOTFS_SPLIT_NAME "\", offset: 0x%06x (0x%06x)\n",
+			__func__, (!strcmp(part->mtd.name, ROOTFS_SPLIT_NAME) ? "updating" : "creating"),
+			(u32) part->offset, (u32) part->mtd.size);
+		name = kmalloc(sizeof(ROOTFS_SPLIT_NAME) + 1, GFP_KERNEL);
+		strcpy(name, ROOTFS_SPLIT_NAME);
+		part->mtd.name = name;
+	} else if ((offset <= 0) && mtd->split) {
+		printk(KERN_INFO "%s: removing partition \"%s\"\n", __func__, mtd->split->name);
+
+		/* mark existing partition as removed */
+		part = PART(mtd->split);
+		name = kmalloc(sizeof(ROOTFS_SPLIT_NAME) + 1, GFP_KERNEL);
+		strcpy(name, ROOTFS_REMOVED_NAME);
+		part->mtd.name = name;
+		part->offset = 0;
+		part->mtd.size = 0;
+	}
+
+	return 0;
+}
+#endif /* CONFIG_MTD_ROOTFS_SPLIT */
+
+static int __init no_rootfs_split(char *str)
+{
+	rootfs_split = 0;
+
+	return 0;
+}
+
+early_param("norootfssplit", no_rootfs_split);
+
 /*
  * This function, given a master MTD object and a partition table, creates
  * and registers slave MTD objects which are bound to the master according to
@@ -659,6 +902,9 @@
 	struct mtd_part *slave;
 	uint64_t cur_offset = 0;
 	int i;
+#ifdef CONFIG_MTD_ROOTFS_SPLIT
+	int ret;
+#endif
 
 	printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name);
 
@@ -673,12 +919,57 @@
 
 		add_mtd_device(&slave->mtd);
 
+		if (!strcmp(parts[i].name, "rootfs")) {
+#ifdef CONFIG_MTD_ROOTFS_ROOT_DEV
+			if (ROOT_DEV == 0) {
+				printk(KERN_NOTICE "mtd: partition \"rootfs\" "
+					"set to be root filesystem\n");
+				ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, slave->mtd.index);
+			}
+#endif
+#ifdef CONFIG_MTD_ROOTFS_SPLIT
+			if (rootfs_split) {
+				ret = split_rootfs_data(master, &slave->mtd, &parts[i]);
+				/* if (ret == 0)
+				 * 	j++; */
+			}
+#endif
+		}
+
 		cur_offset = slave->offset + slave->mtd.size;
 	}
 
 	return 0;
 }
 
+int mtd_device_refresh(struct mtd_info *mtd)
+{
+	int ret = 0;
+
+	if (IS_PART(mtd)) {
+		struct mtd_part *part;
+		struct mtd_info *master;
+
+		part = PART(mtd);
+		master = part->master;
+		if (master->refresh_device)
+			ret = master->refresh_device(master);
+	}
+
+	if (!ret && mtd->refresh_device)
+		ret = mtd->refresh_device(mtd);
+
+#ifdef CONFIG_MTD_ROOTFS_SPLIT
+	if (rootfs_split) {
+		if (!ret && IS_PART(mtd) && !strcmp(mtd->name, "rootfs"))
+			refresh_rootfs_split(mtd);
+	}
+#endif
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(mtd_device_refresh);
+
 static DEFINE_SPINLOCK(part_parser_lock);
 static LIST_HEAD(part_parsers);
 
diff --git a/drivers/mtd/nand/nand_ecc.c b/drivers/mtd/nand/nand_ecc.c
index b7cfe0d..3b6f01d 100644
--- a/drivers/mtd/nand/nand_ecc.c
+++ b/drivers/mtd/nand/nand_ecc.c
@@ -507,8 +507,7 @@
 	if ((bitsperbyte[b0] + bitsperbyte[b1] + bitsperbyte[b2]) == 1)
 		return 1;	/* error in ECC data; no action needed */
 
-	printk(KERN_ERR "uncorrectable error : ");
-	return -1;
+	return -EBADMSG;
 }
 EXPORT_SYMBOL(__nand_correct_data);
 
diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c
index 7f2da69..10f142d 100644
--- a/drivers/mtd/nand/plat_nand.c
+++ b/drivers/mtd/nand/plat_nand.c
@@ -93,7 +93,18 @@
 	}
 
 	/* Scan to find existence of the device */
-	if (nand_scan(&data->mtd, pdata->chip.nr_chips)) {
+	if (nand_scan_ident(&data->mtd, pdata->chip.nr_chips, NULL)) {
+		err = -ENXIO;
+		goto out;
+	}
+
+	if (pdata->chip.chip_fixup) {
+		err = pdata->chip.chip_fixup(&data->mtd);
+		if (err)
+			goto out;
+	}
+
+	if (nand_scan_tail(&data->mtd)) {
 		err = -ENXIO;
 		goto out;
 	}
diff --git a/drivers/mtd/redboot.c b/drivers/mtd/redboot.c
index 48970c1..cc7ed51 100644
--- a/drivers/mtd/redboot.c
+++ b/drivers/mtd/redboot.c
@@ -30,6 +30,8 @@
 #include <linux/mtd/partitions.h>
 #include <linux/module.h>
 
+#define BOARD_CONFIG_PART		"boardconfig"
+
 struct fis_image_desc {
     unsigned char name[16];      // Null terminated name
     uint32_t	  flash_base;    // Address within FLASH of image
@@ -60,6 +62,7 @@
 				    struct mtd_partition **pparts,
 				    struct mtd_part_parser_data *data)
 {
+	unsigned long max_offset = 0;
 	int nrparts = 0;
 	struct fis_image_desc *buf;
 	struct mtd_partition *parts;
@@ -227,14 +230,14 @@
 		}
 	}
 #endif
-	parts = kzalloc(sizeof(*parts)*nrparts + nulllen + namelen, GFP_KERNEL);
+	parts = kzalloc(sizeof(*parts) * (nrparts + 1) + nulllen + namelen + sizeof(BOARD_CONFIG_PART), GFP_KERNEL);
 
 	if (!parts) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
-	nullname = (char *)&parts[nrparts];
+	nullname = (char *)&parts[nrparts + 1];
 #ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
 	if (nulllen > 0) {
 		strcpy(nullname, nullstring);
@@ -253,6 +256,8 @@
 	}
 #endif
 	for ( ; i<nrparts; i++) {
+		if(max_offset < buf[i].flash_base + buf[i].size)
+			max_offset = buf[i].flash_base + buf[i].size;
 		parts[i].size = fl->img->size;
 		parts[i].offset = fl->img->flash_base;
 		parts[i].name = names;
@@ -267,18 +272,33 @@
 #endif
 		names += strlen(names)+1;
 
-#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
 		if(fl->next && fl->img->flash_base + fl->img->size + master->erasesize <= fl->next->img->flash_base) {
-			i++;
-			parts[i].offset = parts[i-1].size + parts[i-1].offset;
-			parts[i].size = fl->next->img->flash_base - parts[i].offset;
-			parts[i].name = nullname;
-		}
+			if (!strcmp(parts[i].name, "rootfs")) {
+				parts[i].size = fl->next->img->flash_base;
+				parts[i].size &= ~(master->erasesize - 1);
+				parts[i].size -= parts[i].offset;
+#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
+				nrparts--;
+			} else {
+				i++;
+				parts[i].offset = parts[i-1].size + parts[i-1].offset;
+				parts[i].size = fl->next->img->flash_base - parts[i].offset;
+				parts[i].name = nullname;
 #endif
+			}
+		}
 		tmp_fl = fl;
 		fl = fl->next;
 		kfree(tmp_fl);
 	}
+	if(master->size - max_offset >= master->erasesize)
+	{
+		parts[nrparts].size = master->size - max_offset;
+		parts[nrparts].offset = max_offset;
+		parts[nrparts].name = names;
+		strcpy(names, BOARD_CONFIG_PART);
+		nrparts++;
+	}
 	ret = nrparts;
 	*pparts = parts;
  out:
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index a6b8ce1..2a900db 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -15,7 +15,7 @@
 obj-$(CONFIG_MDIO) += mdio.o
 obj-$(CONFIG_NET) += Space.o loopback.o
 obj-$(CONFIG_NETCONSOLE) += netconsole.o
-obj-$(CONFIG_PHYLIB) += phy/
+obj-y += phy/
 obj-$(CONFIG_RIONET) += rionet.o
 obj-$(CONFIG_NET_TEAM) += team/
 obj-$(CONFIG_TUN) += tun.o
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index ecbd765..800fe06 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -9415,7 +9415,7 @@
 	}
 
 	err = request_irq(tnapi->irq_vec, tg3_test_isr,
-			  IRQF_SHARED | IRQF_SAMPLE_RANDOM, dev->name, tnapi);
+			  IRQF_SHARED, dev->name, tnapi);
 	if (err)
 		return err;
 
diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c
index b3287c0..a5f872b 100644
--- a/drivers/net/ethernet/realtek/8139cp.c
+++ b/drivers/net/ethernet/realtek/8139cp.c
@@ -645,6 +645,7 @@
 {
 	unsigned tx_head = cp->tx_head;
 	unsigned tx_tail = cp->tx_tail;
+	unsigned bytes_compl = 0, pkts_compl = 0;
 
 	while (tx_tail != tx_head) {
 		struct cp_desc *txd = cp->tx_ring + tx_tail;
@@ -663,6 +664,9 @@
 				 le32_to_cpu(txd->opts1) & 0xffff,
 				 PCI_DMA_TODEVICE);
 
+		bytes_compl += skb->len;
+		pkts_compl++;
+
 		if (status & LastFrag) {
 			if (status & (TxError | TxFIFOUnder)) {
 				netif_dbg(cp, tx_err, cp->dev,
@@ -694,6 +698,7 @@
 
 	cp->tx_tail = tx_tail;
 
+	netdev_completed_queue(cp->dev, pkts_compl, bytes_compl);
 	if (TX_BUFFS_AVAIL(cp) > (MAX_SKB_FRAGS + 1))
 		netif_wake_queue(cp->dev);
 }
@@ -840,6 +845,8 @@
 		wmb();
 	}
 	cp->tx_head = entry;
+
+	netdev_sent_queue(dev, skb->len);
 	netif_dbg(cp, tx_queued, cp->dev, "tx queued, slot %d, skblen %d\n",
 		  entry, skb->len);
 	if (TX_BUFFS_AVAIL(cp) <= (MAX_SKB_FRAGS + 1))
@@ -934,6 +941,8 @@
 
 	cp->rx_tail = 0;
 	cp->tx_head = cp->tx_tail = 0;
+
+	netdev_reset_queue(cp->dev);
 }
 
 static void cp_reset_hw (struct cp_private *cp)
@@ -954,8 +963,38 @@
 
 static inline void cp_start_hw (struct cp_private *cp)
 {
+	dma_addr_t ring_dma;
+
 	cpw16(CpCmd, cp->cpcmd);
+
+	/*
+	 * These (at least TxRingAddr) need to be configured after the
+	 * corresponding bits in CpCmd are enabled. Datasheet v1.6 §6.33
+	 * (C+ Command Register) recommends that these and more be configured
+	 * *after* the [RT]xEnable bits in CpCmd are set. And on some hardware
+	 * it's been observed that the TxRingAddr is actually reset to garbage
+	 * when C+ mode Tx is enabled in CpCmd.
+	 */
+	cpw32_f(HiTxRingAddr, 0);
+	cpw32_f(HiTxRingAddr + 4, 0);
+
+	ring_dma = cp->ring_dma;
+	cpw32_f(RxRingAddr, ring_dma & 0xffffffff);
+	cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16);
+
+	ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE;
+	cpw32_f(TxRingAddr, ring_dma & 0xffffffff);
+	cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16);
+
+	/*
+	 * Strictly speaking, the datasheet says this should be enabled
+	 * *before* setting the descriptor addresses. But what, then, would
+	 * prevent it from doing DMA to random unconfigured addresses?
+	 * This variant appears to work fine.
+	 */
 	cpw8(Cmd, RxOn | TxOn);
+
+	netdev_reset_queue(cp->dev);
 }
 
 static void cp_enable_irq(struct cp_private *cp)
@@ -966,7 +1005,6 @@
 static void cp_init_hw (struct cp_private *cp)
 {
 	struct net_device *dev = cp->dev;
-	dma_addr_t ring_dma;
 
 	cp_reset_hw(cp);
 
@@ -989,17 +1027,6 @@
 
 	cpw8(Config5, cpr8(Config5) & PMEStatus);
 
-	cpw32_f(HiTxRingAddr, 0);
-	cpw32_f(HiTxRingAddr + 4, 0);
-
-	ring_dma = cp->ring_dma;
-	cpw32_f(RxRingAddr, ring_dma & 0xffffffff);
-	cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16);
-
-	ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE;
-	cpw32_f(TxRingAddr, ring_dma & 0xffffffff);
-	cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16);
-
 	cpw16(MultiIntr, 0);
 
 	cpw8_f(Cfg9346, Cfg9346_Lock);
@@ -1188,6 +1215,7 @@
 	cp_clean_rings(cp);
 	rc = cp_init_rings(cp);
 	cp_start_hw(cp);
+	cp_enable_irq(cp);
 
 	netif_wake_queue(dev);
 
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index fbdcdf8..21a5f1c 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -13,6 +13,20 @@
 
 if PHYLIB
 
+config MDIO_BOARDINFO
+	bool
+	default y
+
+config SWCONFIG
+	tristate "Switch configuration API"
+	---help---
+	  Switch configuration API using netlink. This allows
+	  you to configure the VLAN features of certain switches.
+
+config SWCONFIG_LEDS
+	bool "Switch LED trigger support"
+	depends on (SWCONFIG && LEDS_TRIGGERS)
+
 comment "MII PHY device drivers"
 
 config MARVELL_PHY
@@ -92,6 +106,38 @@
 	---help---
 	  Supports the KSZ9021, VSC8201, KS8001 PHYs.
 
+config ADM6996_PHY
+	tristate "Driver for ADM6996 switches"
+	select SWCONFIG
+	---help---
+	  Currently supports the ADM6996FC and ADM6996M switches.
+	  Support for FC is very limited.
+
+config MVSWITCH_PHY
+	tristate "Driver for Marvell 88E6060 switches"
+	select ETHERNET_PACKET_MANGLE
+
+config IP17XX_PHY
+	tristate "Driver for IC+ IP17xx switches"
+	select SWCONFIG
+
+config AR80XX_PHY
+	tristate "Driver for ar8031/ar8033/ar8035 phy"
+
+config AR8216_PHY
+	tristate "Driver for Atheros AR8216 switches"
+	select ETHERNET_PACKET_MANGLE
+	select SWCONFIG
+
+config RTL8306_PHY
+	tristate "Driver for Realtek RTL8306S switches"
+	select SWCONFIG
+
+config MICREL_PHY
+	tristate "Drivers for Micrel/Kendin PHYs"
+	---help---
+	  Currently has a driver for the KSZ8041
+
 config FIXED_PHY
 	bool "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs"
 	depends on PHYLIB=y
@@ -130,8 +176,45 @@
 
 	  If in doubt, say Y.
 
+config RTL8366_SMI
+	tristate "Driver for the RTL8366 SMI interface"
+	depends on GENERIC_GPIO
+	---help---
+	  This module implements the SMI interface protocol which is used
+	  by some RTL8366 ethernet switch devices via the generic GPIO API.
+
+if RTL8366_SMI
+
+config RTL8366_SMI_DEBUG_FS
+	bool "RTL8366 SMI interface debugfs support"
+        depends on DEBUG_FS
+        default n
+
+config RTL8366S_PHY
+	tristate "Driver for the Realtek RTL8366S switch"
+	select SWCONFIG
+
+config RTL8366RB_PHY
+	tristate "Driver for the Realtek RTL8366RB switch"
+	select SWCONFIG
+
+config RTL8367_PHY
+	tristate "Driver for the Realtek RTL8367R/M switches"
+	select SWCONFIG
+
+config RTL8367B_PHY
+	tristate "Driver fot the Realtek RTL8367R-VB switch"
+	select SWCONFIG
+
+endif # RTL8366_SMI
+
 endif # PHYLIB
 
 config MICREL_KS8995MA
 	tristate "Micrel KS8995MA 5-ports 10/100 managed Ethernet switch"
 	depends on SPI
+
+config PSB6970_PHY
+	tristate "Lantiq XWAY Tantos (PSB6970) Ethernet switch"
+	select SWCONFIG
+	select ETHERNET_PACKET_MANGLE
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index e15c83f..014dea3 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -2,7 +2,10 @@
 
 libphy-objs			:= phy.o phy_device.o mdio_bus.o
 
+obj-$(CONFIG_MDIO_BOARDINFO)	+= mdio-boardinfo.o
+
 obj-$(CONFIG_PHYLIB)		+= libphy.o
+obj-$(CONFIG_SWCONFIG)		+= swconfig.o
 obj-$(CONFIG_MARVELL_PHY)	+= marvell.o
 obj-$(CONFIG_DAVICOM_PHY)	+= davicom.o
 obj-$(CONFIG_CICADA_PHY)	+= cicada.o
@@ -13,8 +16,21 @@
 obj-$(CONFIG_BROADCOM_PHY)	+= broadcom.o
 obj-$(CONFIG_BCM63XX_PHY)	+= bcm63xx.o
 obj-$(CONFIG_ICPLUS_PHY)	+= icplus.o
+obj-$(CONFIG_ADM6996_PHY)	+= adm6996.o
+obj-$(CONFIG_MVSWITCH_PHY)	+= mvswitch.o
+obj-$(CONFIG_IP17XX_PHY)	+= ip17xx.o
 obj-$(CONFIG_REALTEK_PHY)	+= realtek.o
+obj-$(CONFIG_AR80XX_PHY)	+= ar80xx.o
+obj-$(CONFIG_AR8216_PHY)	+= ar8216.o
+obj-$(CONFIG_RTL8306_PHY)	+= rtl8306.o
+obj-$(CONFIG_RTL8366_SMI)	+= rtl8366_smi.o
+obj-$(CONFIG_RTL8366S_PHY)	+= rtl8366s.o
+obj-$(CONFIG_RTL8366RB_PHY)	+= rtl8366rb.o
+obj-$(CONFIG_RTL8367_PHY)	+= rtl8367.o
+obj-$(CONFIG_RTL8367B_PHY)	+= rtl8367b.o
 obj-$(CONFIG_LSI_ET1011C_PHY)	+= et1011c.o
+obj-$(CONFIG_MICREL_PHY)	+= micrel.o
+obj-$(CONFIG_PSB6970_PHY)	+= psb6970.o
 obj-$(CONFIG_FIXED_PHY)		+= fixed.o
 obj-$(CONFIG_MDIO_BITBANG)	+= mdio-bitbang.o
 obj-$(CONFIG_MDIO_GPIO)		+= mdio-gpio.o
diff --git a/drivers/net/phy/mdio-boardinfo.c b/drivers/net/phy/mdio-boardinfo.c
new file mode 100644
index 0000000..9b8aaed
--- /dev/null
+++ b/drivers/net/phy/mdio-boardinfo.c
@@ -0,0 +1,58 @@
+/*
+ * mdio-boardinfo.c - collect pre-declarations of PHY devices
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the 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/phy.h>
+#include <linux/slab.h>
+#include <linux/export.h>
+#include <linux/mutex.h>
+#include <linux/phy.h>
+
+#include "mdio-boardinfo.h"
+
+/*
+ * These symbols are exported ONLY FOR the mdio_bus component.
+ * No other users will be supported.
+ */
+
+LIST_HEAD(__mdio_board_list);
+EXPORT_SYMBOL_GPL(__mdio_board_list);
+
+DEFINE_MUTEX(__mdio_board_lock);
+EXPORT_SYMBOL_GPL(__mdio_board_lock);
+
+/**
+ * mdio_register_board_info - register PHY devices for a given board
+ * @info: array of chip descriptors
+ * @n: how many descriptors are provided
+ * Context: can sleep
+ *
+ * The board info passed can safely be __initdata ... but be careful of
+ * any embedded pointers (platform_data, etc), they're copied as-is.
+ */
+int __init
+mdiobus_register_board_info(struct mdio_board_info const *info, unsigned n)
+{
+	struct mdio_board_entry *be;
+	int i;
+
+	be = kzalloc(n * sizeof(*be), GFP_KERNEL);
+	if (!be)
+		return -ENOMEM;
+
+	for (i = 0; i < n; i++, be++, info++) {
+		memcpy(&be->board_info, info, sizeof(*info));
+		mutex_lock(&__mdio_board_lock);
+		list_add_tail(&be->list, &__mdio_board_list);
+		mutex_unlock(&__mdio_board_lock);
+	}
+
+	return 0;
+}
diff --git a/drivers/net/phy/mdio-boardinfo.h b/drivers/net/phy/mdio-boardinfo.h
new file mode 100644
index 0000000..28fbc0d
--- /dev/null
+++ b/drivers/net/phy/mdio-boardinfo.h
@@ -0,0 +1,22 @@
+/*
+ * mdio-boardinfo.h - boardinfo interface internal to the mdio_bus component
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the 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/mutex.h>
+
+struct mdio_board_entry {
+	struct list_head	list;
+	struct mdio_board_info	board_info;
+};
+
+/* __mdio_board_lock protects __mdio_board_list
+ * only mdio_bus components are allowed to use these symbols.
+ */
+extern struct mutex __mdio_board_lock;
+extern struct list_head __mdio_board_list;
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 8985cc6..707f4a0 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -36,6 +36,8 @@
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 
+#include "mdio-boardinfo.h"
+
 /**
  * mdiobus_alloc_size - allocate a mii_bus structure
  * @size: extra amount of memory to allocate for private storage.
@@ -192,15 +194,33 @@
 }
 EXPORT_SYMBOL(mdiobus_free);
 
+static void mdiobus_setup_phydev_from_boardinfo(struct mii_bus *bus,
+						struct phy_device *phydev,
+						struct mdio_board_info *bi)
+{
+	if (strcmp(bus->id, bi->bus_id) ||
+	    bi->phy_addr != phydev->addr)
+		return;
+
+	phydev->dev.platform_data = (void *) bi->platform_data;
+}
+
 struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr)
 {
 	struct phy_device *phydev;
+	struct mdio_board_entry *be;
 	int err;
 
 	phydev = get_phy_device(bus, addr);
 	if (IS_ERR(phydev) || phydev == NULL)
 		return phydev;
 
+	mutex_lock(&__mdio_board_lock);
+	list_for_each_entry(be, &__mdio_board_list, list)
+		mdiobus_setup_phydev_from_boardinfo(bus, phydev,
+						    &be->board_info);
+	mutex_unlock(&__mdio_board_lock);
+
 	err = phy_device_register(phydev);
 	if (err) {
 		phy_device_free(phydev);
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 3cbda08..ecfef67 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -106,6 +106,9 @@
 {
 	int retval;
 
+	if (phydev->drv->aneg_done)
+		return phydev->drv->aneg_done(phydev);
+
 	retval = phy_read(phydev, MII_BMSR);
 
 	return (retval < 0) ? retval : (retval & BMSR_ANEGCOMPLETE);
@@ -299,6 +302,50 @@
 }
 EXPORT_SYMBOL(phy_ethtool_gset);
 
+int phy_ethtool_ioctl(struct phy_device *phydev, void *useraddr)
+{
+	u32 cmd;
+	int tmp;
+	struct ethtool_cmd ecmd = { ETHTOOL_GSET };
+	struct ethtool_value edata = { ETHTOOL_GLINK };
+
+	if (get_user(cmd, (u32 *) useraddr))
+		return -EFAULT;
+
+	switch (cmd) {
+	case ETHTOOL_GSET:
+		phy_ethtool_gset(phydev, &ecmd);
+		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
+			return -EFAULT;
+		return 0;
+
+	case ETHTOOL_SSET:
+		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
+			return -EFAULT;
+		return phy_ethtool_sset(phydev, &ecmd);
+
+	case ETHTOOL_NWAY_RST:
+		/* if autoneg is off, it's an error */
+		tmp = phy_read(phydev, MII_BMCR);
+		if (tmp & BMCR_ANENABLE) {
+			tmp |= (BMCR_ANRESTART);
+			phy_write(phydev, MII_BMCR, tmp);
+			return 0;
+		}
+		return -EINVAL;
+
+	case ETHTOOL_GLINK:
+		edata.data = (phy_read(phydev,
+				MII_BMSR) & BMSR_LSTATUS) ? 1 : 0;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+
+	return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL(phy_ethtool_ioctl);
+
 /**
  * phy_mii_ioctl - generic PHY MII ioctl interface
  * @phydev: the phy_device struct
@@ -474,7 +521,7 @@
 	int idx;
 
 	idx = phy_find_setting(phydev->speed, phydev->duplex);
-	
+
 	idx++;
 
 	idx = phy_find_valid(idx, phydev->supported);
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index f320f46..5ffeaf3 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -705,6 +705,9 @@
 {
 	int status;
 
+	if (phydev->drv->update_link)
+		return phydev->drv->update_link(phydev);
+
 	/* Do a fake read */
 	status = phy_read(phydev, MII_BMSR);
 
diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c
index bc9a4bb..49c6da9 100644
--- a/drivers/net/ppp/pppoe.c
+++ b/drivers/net/ppp/pppoe.c
@@ -856,7 +856,7 @@
 		goto end;
 
 
-	skb = sock_wmalloc(sk, total_len + dev->hard_header_len + 32,
+	skb = sock_wmalloc(sk, total_len + dev->hard_header_len + 32 + NET_SKB_PAD,
 			   0, GFP_KERNEL);
 	if (!skb) {
 		error = -ENOMEM;
@@ -864,7 +864,7 @@
 	}
 
 	/* Reserve space for headers. */
-	skb_reserve(skb, dev->hard_header_len);
+	skb_reserve(skb, dev->hard_header_len + NET_SKB_PAD);
 	skb_reset_network_header(skb);
 
 	skb->dev = dev;
diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c
index aaaca9a..3f575af 100644
--- a/drivers/net/wan/ixp4xx_hss.c
+++ b/drivers/net/wan/ixp4xx_hss.c
@@ -10,6 +10,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/module.h>
 #include <linux/bitops.h>
 #include <linux/cdev.h>
 #include <linux/dma-mapping.h>
diff --git a/drivers/net/wireless/hostap/hostap.h b/drivers/net/wireless/hostap/hostap.h
index ce8721f..c638a83 100644
--- a/drivers/net/wireless/hostap/hostap.h
+++ b/drivers/net/wireless/hostap/hostap.h
@@ -90,6 +90,7 @@
 extern const struct ethtool_ops prism2_ethtool_ops;
 
 int hostap_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
+int hostap_restore_power(struct net_device *dev);
 
 
 #endif /* HOSTAP_H */
diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c
index e1f4102..8da6dbe 100644
--- a/drivers/net/wireless/hostap/hostap_ap.c
+++ b/drivers/net/wireless/hostap/hostap_ap.c
@@ -2340,13 +2340,13 @@
 		addr[count].sa_family = ARPHRD_ETHER;
 		memcpy(addr[count].sa_data, sta->addr, ETH_ALEN);
 		if (sta->last_rx_silence == 0)
-			qual[count].qual = sta->last_rx_signal < 27 ?
-				0 : (sta->last_rx_signal - 27) * 92 / 127;
+                        qual[count].qual = (sta->last_rx_signal - 156) == 0 ?
+                                0 : (sta->last_rx_signal - 156) * 92 / 64;
 		else
-			qual[count].qual = sta->last_rx_signal -
-				sta->last_rx_silence - 35;
-		qual[count].level = HFA384X_LEVEL_TO_dBm(sta->last_rx_signal);
-		qual[count].noise = HFA384X_LEVEL_TO_dBm(sta->last_rx_silence);
+                        qual[count].qual = (sta->last_rx_signal -
+                                sta->last_rx_silence) * 92 / 64;
+                qual[count].level = sta->last_rx_signal;
+                qual[count].noise = sta->last_rx_silence;
 		qual[count].updated = sta->last_rx_updated;
 
 		sta->last_rx_updated = IW_QUAL_DBM;
@@ -2412,13 +2412,13 @@
 		memset(&iwe, 0, sizeof(iwe));
 		iwe.cmd = IWEVQUAL;
 		if (sta->last_rx_silence == 0)
-			iwe.u.qual.qual = sta->last_rx_signal < 27 ?
-				0 : (sta->last_rx_signal - 27) * 92 / 127;
+	                iwe.u.qual.qual = (sta->last_rx_signal -156) == 0 ?
+	                        0 : (sta->last_rx_signal - 156) * 92 / 64;
 		else
-			iwe.u.qual.qual = sta->last_rx_signal -
-				sta->last_rx_silence - 35;
-		iwe.u.qual.level = HFA384X_LEVEL_TO_dBm(sta->last_rx_signal);
-		iwe.u.qual.noise = HFA384X_LEVEL_TO_dBm(sta->last_rx_silence);
+                        iwe.u.qual.qual = (sta->last_rx_signal -
+                                sta->last_rx_silence) * 92 / 64;
+                iwe.u.qual.level = sta->last_rx_signal;
+                iwe.u.qual.noise = sta->last_rx_silence;
 		iwe.u.qual.updated = sta->last_rx_updated;
 		iwe.len = IW_EV_QUAL_LEN;
 		current_ev = iwe_stream_add_event(info, current_ev, end_buf,
diff --git a/drivers/net/wireless/hostap/hostap_config.h b/drivers/net/wireless/hostap/hostap_config.h
index 2c8f71f..d37d1fd 100644
--- a/drivers/net/wireless/hostap/hostap_config.h
+++ b/drivers/net/wireless/hostap/hostap_config.h
@@ -45,4 +45,9 @@
  */
 /* #define PRISM2_NO_STATION_MODES */
 
+/* Enable TX power Setting functions
+ * (min att = -128 , max att =  127)
+ */
+#define RAW_TXPOWER_SETTING
+
 #endif /* HOSTAP_CONFIG_H */
diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c
index a8bddd8..1e13d2a 100644
--- a/drivers/net/wireless/hostap/hostap_hw.c
+++ b/drivers/net/wireless/hostap/hostap_hw.c
@@ -932,6 +932,7 @@
 			prism2_hw_reset(dev);
 	}
 
+	hostap_restore_power(dev);
 	return res;
 }
 
diff --git a/drivers/net/wireless/hostap/hostap_info.c b/drivers/net/wireless/hostap/hostap_info.c
index 47932b2..23074ed 100644
--- a/drivers/net/wireless/hostap/hostap_info.c
+++ b/drivers/net/wireless/hostap/hostap_info.c
@@ -434,6 +434,11 @@
 	}
 
 	/* Get BSSID if we have a valid AP address */
+
+	if ( val == HFA384X_LINKSTATUS_CONNECTED ||
+	     val == HFA384X_LINKSTATUS_DISCONNECTED )
+			hostap_restore_power(local->dev);
+
 	if (connected) {
 		netif_carrier_on(local->dev);
 		netif_carrier_on(local->ddev);
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c
index 18054d9..756e31f 100644
--- a/drivers/net/wireless/hostap/hostap_ioctl.c
+++ b/drivers/net/wireless/hostap/hostap_ioctl.c
@@ -1478,23 +1478,20 @@
 		val = 255;
 
 	tmp = val;
-	tmp >>= 2;
 
-	return -12 - tmp;
+	return tmp;
 }
 
 static u16 prism2_txpower_dBm_to_hfa386x(int val)
 {
 	signed char tmp;
 
-	if (val > 20)
-		return 128;
-	else if (val < -43)
+	if (val > 127)
 		return 127;
+	else if (val < -128)
+		return 128;
 
 	tmp = val;
-	tmp = -12 - tmp;
-	tmp <<= 2;
 
 	return (unsigned char) tmp;
 }
@@ -4057,3 +4054,35 @@
 
 	return ret;
 }
+
+/* BUG FIX: Restore power setting value when lost due to F/W bug */
+
+int hostap_restore_power(struct net_device *dev)
+{
+        struct hostap_interface *iface = netdev_priv(dev);
+       local_info_t *local = iface->local;
+
+       u16 val;
+       int ret = 0;
+
+       if (local->txpower_type == PRISM2_TXPOWER_OFF) {
+                       val = 0xff; /* use all standby and sleep modes */
+                       ret = local->func->cmd(dev, HFA384X_CMDCODE_WRITEMIF,
+                                              HFA386X_CR_A_D_TEST_MODES2,
+                                              &val, NULL);
+       }
+
+#ifdef RAW_TXPOWER_SETTING
+       if (local->txpower_type == PRISM2_TXPOWER_FIXED) {
+               val = HFA384X_TEST_CFG_BIT_ALC;
+               local->func->cmd(dev, HFA384X_CMDCODE_TEST |
+                                (HFA384X_TEST_CFG_BITS << 8), 0, &val, NULL);
+               val = prism2_txpower_dBm_to_hfa386x(local->txpower);
+               ret = (local->func->cmd(dev, HFA384X_CMDCODE_WRITEMIF,
+                            HFA386X_CR_MANUAL_TX_POWER, &val, NULL));
+       }
+#endif /* RAW_TXPOWER_SETTING */
+       return (ret ? -EOPNOTSUPP : 0);
+}
+
+EXPORT_SYMBOL(hostap_restore_power);
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 37856f7..1dd3ab8 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -51,6 +51,12 @@
           The PCI device frontend driver allows the kernel to import arbitrary
           PCI devices from a PCI backend to support PCI driver domains.
 
+config PCI_DISABLE_COMMON_QUIRKS
+	bool "PCI disable common quirks"
+	depends on PCI
+	help
+	  If you don't know what to do here, say N.
+
 config HT_IRQ
 	bool "Interrupts on hypertransport devices"
 	default y
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 78fda9c..7c31a7a 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -105,6 +105,7 @@
 }
 DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, quirk_mmio_always_on);
 
+#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS
 /* The Mellanox Tavor device gives false positive parity errors
  * Mark this device with a broken_parity_status, to allow
  * PCI scanning code to "skip" this now blacklisted device.
@@ -1990,7 +1991,9 @@
 	}
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1_53c810);
+#endif /* !CONFIG_PCI_DISABLE_COMMON_QUIRKS */
 
+#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS
 /* Enable 1k I/O space granularity on the Intel P64H2 */
 static void __devinit quirk_p64h2_1k_io(struct pci_dev *dev)
 {
@@ -2666,6 +2669,7 @@
 			quirk_msi_intx_disable_bug);
 
 #endif /* CONFIG_PCI_MSI */
+#endif /* !CONFIG_PCI_DISABLE_COMMON_QUIRKS */
 
 /* Allow manual resource allocation for PCI hotplug bridges
  * via pci=hpmemsize=nnM and pci=hpiosize=nnM parameters. For
diff --git a/drivers/power/pda_power.c b/drivers/power/pda_power.c
index fd49689..26cc30d 100644
--- a/drivers/power/pda_power.c
+++ b/drivers/power/pda_power.c
@@ -24,11 +24,7 @@
 
 static inline unsigned int get_irq_flags(struct resource *res)
 {
-	unsigned int flags = IRQF_SAMPLE_RANDOM | IRQF_SHARED;
-
-	flags |= res->flags & IRQF_TRIGGER_MASK;
-
-	return flags;
+	return IRQF_SHARED | (res->flags & IRQF_TRIGGER_MASK);
 }
 
 static struct device *dev;
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 3a125b8..f7602b4 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -379,6 +379,15 @@
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-rv3029c2.
 
+config RTC_DRV_PT7C4338
+	tristate "Pericom Technology Inc. PT7C4338 RTC"
+	help
+	  If you say yes here you get support for the Pericom Technology
+	  Inc. PT7C4338 RTC chip.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called rtc-pt7c4338.
+
 endif # I2C
 
 comment "SPI RTC drivers"
@@ -719,6 +728,15 @@
 	  If you say yes here you get support for the RTC subsystem of the
 	  NUC910/NUC920 used in embedded systems.
 
+config RTC_DRV_RTC7301
+	tristate "Epson RTC-7301 SF/DG"
+	help
+	  If you say Y here you will get support for the
+	  Epson RTC-7301 SF/DG RTC chips.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called rtc-7301.
+
 comment "on-CPU RTC drivers"
 
 config RTC_DRV_DAVINCI
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 6e69823..b3d8b1e 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -79,6 +79,7 @@
 obj-$(CONFIG_RTC_DRV_PL031)	+= rtc-pl031.o
 obj-$(CONFIG_RTC_DRV_PM8XXX)	+= rtc-pm8xxx.o
 obj-$(CONFIG_RTC_DRV_PS3)	+= rtc-ps3.o
+obj-$(CONFIG_RTC_DRV_PT7C4338)	+= rtc-pt7c4338.o
 obj-$(CONFIG_RTC_DRV_PUV3)	+= rtc-puv3.o
 obj-$(CONFIG_RTC_DRV_PXA)	+= rtc-pxa.o
 obj-$(CONFIG_RTC_DRV_R9701)	+= rtc-r9701.o
@@ -86,6 +87,7 @@
 obj-$(CONFIG_RTC_DRV_RS5C313)	+= rtc-rs5c313.o
 obj-$(CONFIG_RTC_DRV_RS5C348)	+= rtc-rs5c348.o
 obj-$(CONFIG_RTC_DRV_RS5C372)	+= rtc-rs5c372.o
+obj-$(CONFIG_RTC_DRV_RTC7301)	+= rtc-rtc7301.o
 obj-$(CONFIG_RTC_DRV_RV3029C2)	+= rtc-rv3029c2.o
 obj-$(CONFIG_RTC_DRV_RX8025)	+= rtc-rx8025.o
 obj-$(CONFIG_RTC_DRV_RX8581)	+= rtc-rx8581.o
diff --git a/drivers/rtc/rtc-pt7c4338.c b/drivers/rtc/rtc-pt7c4338.c
new file mode 100644
index 0000000..75a0817
--- /dev/null
+++ b/drivers/rtc/rtc-pt7c4338.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright 2010 Freescale Semiconductor, Inc.
+ *
+ * Author:	Priyanka Jain <Priyanka.Jain@freescale.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU 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
+ */
+
+/*
+ * This file provides Date & Time support (no alarms) for PT7C4338 chip.
+ *
+ * This file is based on drivers/rtc/rtc-ds1307.c
+ *
+ * PT7C4338 chip is manufactured by Pericom Technology Inc.
+ * It is a serial real-time clock which provides
+ * 1)Low-power clock/calendar.
+ * 2)Programmable square-wave output.
+ * It has 56 bytes of nonvolatile RAM.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+
+/* RTC register addresses */
+#define PT7C4338_REG_SECONDS          0x00
+#define PT7C4338_REG_MINUTES          0x01
+#define PT7C4338_REG_HOURS            0x02
+#define PT7C4338_REG_AMPM             0x02
+#define PT7C4338_REG_DAY              0x03
+#define PT7C4338_REG_DATE             0x04
+#define PT7C4338_REG_MONTH            0x05
+#define PT7C4338_REG_YEAR             0x06
+#define PT7C4338_REG_CTRL_STAT        0x07
+
+/* RTC second register address bit */
+#define PT7C4338_SEC_BIT_CH           0x80	/*Clock Halt (in Register 0)*/
+
+/* RTC control and status register bits */
+#define PT7C4338_CTRL_STAT_BIT_RS0    0x1	/*Rate select 0*/
+#define PT7C4338_CTRL_STAT_BIT_RS1    0x2	/*Rate select 1*/
+#define PT7C4338_CTRL_STAT_BIT_SQWE   0x10	/*Square Wave Enable*/
+#define PT7C4338_CTRL_STAT_BIT_OSF    0x20	/*Oscillator Stop Flag*/
+#define PT7C4338_CTRL_STAT_BIT_OUT    0x80	/*Output Level Control*/
+
+static const struct i2c_device_id pt7c4338_id[] = {
+	{ "pt7c4338", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, pt7c4338_id);
+
+struct pt7c4338{
+	struct i2c_client *client;
+	struct rtc_device *rtc;
+};
+
+static int pt7c4338_read_time(struct device *dev, struct rtc_time *time)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	int ret;
+	u8 buf[7];
+	u8 year, month, day, hour, minute, second;
+	u8 week, twelve_hr, am_pm;
+
+	ret = i2c_smbus_read_i2c_block_data(client,
+			PT7C4338_REG_SECONDS, 7, buf);
+	if (ret < 0)
+		return ret;
+	if (ret < 7)
+		return -EIO;
+
+	second = buf[0];
+	minute = buf[1];
+	hour = buf[2];
+	week = buf[3];
+	day = buf[4];
+	month = buf[5];
+	year = buf[6];
+
+	/* Extract additional information for AM/PM */
+	twelve_hr = hour & 0x40;
+	am_pm = hour & 0x20;
+
+	/* Write to rtc_time structure */
+	time->tm_sec = bcd2bin(second & 0x7f);
+	time->tm_min = bcd2bin(minute & 0x7f);
+	if (twelve_hr) {
+		/* Convert to 24 hr */
+		if (am_pm)
+			time->tm_hour = bcd2bin(hour & 0x10) + 12;
+		else
+			time->tm_hour = bcd2bin(hour & 0xBF);
+	} else {
+		time->tm_hour = bcd2bin(hour);
+	}
+
+	time->tm_wday = bcd2bin(week & 0x07) - 1;
+	time->tm_mday = bcd2bin(day & 0x3f);
+	time->tm_mon = bcd2bin(month & 0x1F) - 1;
+	/* assume 20YY not 19YY */
+	time->tm_year = bcd2bin(year) + 100;
+
+	return 0;
+}
+
+static int pt7c4338_set_time(struct device *dev, struct rtc_time *time)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	u8 buf[7];
+
+	/* Extract time from rtc_time and load into pt7c4338*/
+	buf[0] = bin2bcd(time->tm_sec);
+	buf[1] = bin2bcd(time->tm_min);
+	buf[2] = bin2bcd(time->tm_hour);
+	buf[3] = bin2bcd(time->tm_wday + 1); /* Day of the week */
+	buf[4] = bin2bcd(time->tm_mday); /* Date */
+	buf[5] = bin2bcd(time->tm_mon + 1);
+
+	/* assume 20YY not 19YY */
+	if (time->tm_year >= 100)
+		buf[6] = bin2bcd(time->tm_year - 100);
+	else
+		buf[6] = bin2bcd(time->tm_year);
+
+	return i2c_smbus_write_i2c_block_data(client,
+					PT7C4338_REG_SECONDS, 7, buf);
+}
+
+static const struct rtc_class_ops pt7c4338_rtc_ops = {
+	.read_time = pt7c4338_read_time,
+	.set_time = pt7c4338_set_time,
+};
+
+static int pt7c4338_probe(struct i2c_client *client,
+		const struct i2c_device_id *id)
+{
+	struct pt7c4338 *pt7c4338;
+	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+	int ret;
+
+	pt7c4338 = kzalloc(sizeof(struct pt7c4338), GFP_KERNEL);
+	if (!pt7c4338)
+		return -ENOMEM;
+
+	pt7c4338->client = client;
+	i2c_set_clientdata(client, pt7c4338);
+	pt7c4338->rtc = rtc_device_register(client->name, &client->dev,
+					&pt7c4338_rtc_ops, THIS_MODULE);
+	if (IS_ERR(pt7c4338->rtc)) {
+		ret = PTR_ERR(pt7c4338->rtc);
+		dev_err(&client->dev, "unable to register the class device\n");
+		goto out_free;
+	}
+
+	return 0;
+out_free:
+	i2c_set_clientdata(client, NULL);
+	kfree(pt7c4338);
+	return ret;
+}
+
+static int __devexit pt7c4338_remove(struct i2c_client *client)
+{
+	struct pt7c4338 *pt7c4338 = i2c_get_clientdata(client);
+
+	rtc_device_unregister(pt7c4338->rtc);
+	i2c_set_clientdata(client, NULL);
+	kfree(pt7c4338);
+	return 0;
+}
+
+static struct i2c_driver pt7c4338_driver = {
+	.driver = {
+		.name = "rtc-pt7c4338",
+		.owner = THIS_MODULE,
+	},
+	.probe = pt7c4338_probe,
+	.remove = __devexit_p(pt7c4338_remove),
+	.id_table = pt7c4338_id,
+};
+
+static int __init pt7c4338_init(void)
+{
+	return i2c_add_driver(&pt7c4338_driver);
+}
+
+static void __exit pt7c4338_exit(void)
+{
+	i2c_del_driver(&pt7c4338_driver);
+}
+
+module_init(pt7c4338_init);
+module_exit(pt7c4338_exit);
+
+MODULE_AUTHOR("Priyanka Jain <Priyanka.Jain@freescale.com>");
+MODULE_DESCRIPTION("pericom Technology Inc. PT7C4338 RTC Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-rtc7301.c b/drivers/rtc/rtc-rtc7301.c
new file mode 100644
index 0000000..c3d0256
--- /dev/null
+++ b/drivers/rtc/rtc-rtc7301.c
@@ -0,0 +1,219 @@
+/*
+ * Driver for Epson RTC-7301SF/DG
+ *
+ * Copyright (C) 2009 Jose Vasconcellos
+ *
+ * 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/rtc.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/bcd.h>
+
+#define RTC_NAME "rtc7301"
+#define RTC_VERSION "0.1"
+
+/* Epson RTC-7301 register addresses */
+#define RTC7301_SEC		0x00
+#define RTC7301_SEC10		0x01
+#define RTC7301_MIN		0x02
+#define RTC7301_MIN10		0x03
+#define RTC7301_HOUR		0x04
+#define RTC7301_HOUR10		0x05
+#define RTC7301_WEEKDAY		0x06
+#define RTC7301_DAY		0x07
+#define RTC7301_DAY10		0x08
+#define RTC7301_MON		0x09
+#define RTC7301_MON10		0x0A
+#define RTC7301_YEAR		0x0B
+#define RTC7301_YEAR10		0x0C
+#define RTC7301_YEAR100		0x0D
+#define RTC7301_YEAR1000	0x0E
+#define RTC7301_CTRLREG		0x0F
+
+static uint8_t __iomem *rtc7301_base;
+
+#define read_reg(offset) (readb(rtc7301_base + offset) & 0xf)
+#define write_reg(offset, data) writeb(data, rtc7301_base + (offset))
+
+#define rtc7301_isbusy() (read_reg(RTC7301_CTRLREG) & 1)
+
+static void rtc7301_init_settings(void)
+{
+	int i;
+
+	write_reg(RTC7301_CTRLREG, 2);
+	write_reg(RTC7301_YEAR1000, 2);
+	udelay(122);
+
+	/* bank 1 */
+	write_reg(RTC7301_CTRLREG, 6);
+	for (i=0; i<15; i++)
+		write_reg(i, 0);
+
+	/* bank 2 */
+	write_reg(RTC7301_CTRLREG, 14);
+	for (i=0; i<15; i++)
+		write_reg(i, 0);
+	write_reg(RTC7301_CTRLREG, 0);
+}
+
+static int rtc7301_get_datetime(struct device *dev, struct rtc_time *dt)
+{
+	int cnt;
+	uint8_t buf[16];
+
+	cnt = 0;
+	while (rtc7301_isbusy()) {
+		udelay(244);
+		if (cnt++ > 100) {
+			dev_err(dev, "%s: timeout error %x\n", __func__, rtc7301_base[RTC7301_CTRLREG]);
+			return -EIO;
+		}
+	}
+
+	for (cnt=0; cnt<16; cnt++)
+		buf[cnt] = read_reg(cnt);
+
+	if (buf[RTC7301_SEC10] & 8) {
+		dev_err(dev, "%s: RTC not set\n", __func__);
+		return -EINVAL;
+	}
+
+	memset(dt, 0, sizeof(*dt));
+
+	dt->tm_sec =  buf[RTC7301_SEC] + buf[RTC7301_SEC10]*10;
+	dt->tm_min =  buf[RTC7301_MIN] + buf[RTC7301_MIN10]*10;
+	dt->tm_hour = buf[RTC7301_HOUR] + buf[RTC7301_HOUR10]*10;
+
+	dt->tm_mday = buf[RTC7301_DAY] + buf[RTC7301_DAY10]*10;
+	dt->tm_mon =  buf[RTC7301_MON] + buf[RTC7301_MON10]*10 - 1;
+	dt->tm_year = buf[RTC7301_YEAR] + buf[RTC7301_YEAR10]*10 +
+		      buf[RTC7301_YEAR100]*100 +
+		      ((buf[RTC7301_YEAR1000] & 3)*1000) - 1900;
+
+	/* the rtc device may contain illegal values on power up
+	 * according to the data sheet. make sure they are valid.
+	 */
+
+	return rtc_valid_tm(dt);
+}
+
+static int rtc7301_set_datetime(struct device *dev, struct rtc_time *dt)
+{
+	int data;
+
+	data = dt->tm_year + 1900;
+	if (data >= 2100 || data < 1900)
+		return -EINVAL;
+
+	write_reg(RTC7301_CTRLREG, 2);
+       	udelay(122);
+
+	data = bin2bcd(dt->tm_sec);
+	write_reg(RTC7301_SEC, data);
+	write_reg(RTC7301_SEC10, (data >> 4));
+
+	data = bin2bcd(dt->tm_min);
+	write_reg(RTC7301_MIN, data );
+	write_reg(RTC7301_MIN10, (data >> 4));
+
+	data = bin2bcd(dt->tm_hour);
+	write_reg(RTC7301_HOUR, data);
+	write_reg(RTC7301_HOUR10, (data >> 4));
+
+	data = bin2bcd(dt->tm_mday);
+	write_reg(RTC7301_DAY, data);
+	write_reg(RTC7301_DAY10, (data>> 4));
+
+	data = bin2bcd(dt->tm_mon + 1);
+	write_reg(RTC7301_MON, data);
+	write_reg(RTC7301_MON10, (data >> 4));
+
+	data = bin2bcd(dt->tm_year % 100);
+	write_reg(RTC7301_YEAR, data);
+	write_reg(RTC7301_YEAR10, (data >> 4));
+	data = bin2bcd((1900 + dt->tm_year) / 100);
+	write_reg(RTC7301_YEAR100, data);
+
+	data = bin2bcd(dt->tm_wday);
+	write_reg(RTC7301_WEEKDAY, data);
+
+	write_reg(RTC7301_CTRLREG, 0);
+
+	return 0;
+}
+
+static const struct rtc_class_ops rtc7301_rtc_ops = {
+	.read_time	= rtc7301_get_datetime,
+	.set_time	= rtc7301_set_datetime,
+};
+
+static int __devinit rtc7301_probe(struct platform_device *pdev)
+{
+	struct rtc_device *rtc;
+	struct resource *res;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENOENT;
+
+	rtc7301_base = ioremap_nocache(res->start, 0x1000 /*res->end - res->start + 1*/);
+	if (!rtc7301_base)
+		return -EINVAL;
+
+	rtc = rtc_device_register(RTC_NAME, &pdev->dev,
+				&rtc7301_rtc_ops, THIS_MODULE);
+	if (IS_ERR(rtc)) {
+		iounmap(rtc7301_base);
+		return PTR_ERR(rtc);
+	}
+
+	platform_set_drvdata(pdev, rtc);
+
+	rtc7301_init_settings();
+	return 0;
+}
+
+static int __devexit rtc7301_remove(struct platform_device *pdev)
+{
+	struct rtc_device *rtc = platform_get_drvdata(pdev);
+
+	if (rtc)
+		rtc_device_unregister(rtc);
+	if (rtc7301_base)
+		iounmap(rtc7301_base);
+	return 0;
+}
+
+static struct platform_driver rtc7301_driver = {
+	.driver = {
+		.name	= RTC_NAME,
+		.owner	= THIS_MODULE,
+	},
+	.probe	= rtc7301_probe,
+	.remove = __devexit_p(rtc7301_remove),
+};
+
+static __init int rtc7301_init(void)
+{
+	return platform_driver_register(&rtc7301_driver);
+}
+module_init(rtc7301_init);
+
+static __exit void rtc7301_exit(void)
+{
+	platform_driver_unregister(&rtc7301_driver);
+}
+module_exit(rtc7301_exit);
+
+MODULE_DESCRIPTION("Epson 7301 RTC driver");
+MODULE_AUTHOR("Jose Vasconcellos <jvasco@verizon.net>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" RTC_NAME);
+MODULE_VERSION(RTC_VERSION);
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 8293658..f62424f 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -154,6 +154,15 @@
 	  GPIO operations, you should be able to leverage that for better
 	  speed with a custom version of this driver; see the source code.
 
+config SPI_GPIO_OLD
+	tristate "Old GPIO API based bitbanging SPI controller (DEPRECATED)"
+	depends on SPI_MASTER && GENERIC_GPIO
+	select SPI_BITBANG
+	help
+	  This code is deprecated. Please use the new mainline SPI-GPIO driver.
+
+	  If unsure, say N.
+
 config SPI_IMX
 	tristate "Freescale i.MX SPI controllers"
 	depends on ARCH_MXC
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 61c3261..1514c1d 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -29,6 +29,7 @@
 obj-$(CONFIG_SPI_FSL_ESPI)		+= spi-fsl-espi.o
 obj-$(CONFIG_SPI_FSL_SPI)		+= spi-fsl-spi.o
 obj-$(CONFIG_SPI_GPIO)			+= spi-gpio.o
+obj-$(CONFIG_SPI_GPIO_OLD)		+= spi_gpio_old.o
 obj-$(CONFIG_SPI_IMX)			+= spi-imx.o
 obj-$(CONFIG_SPI_LM70_LLP)		+= spi-lm70llp.o
 obj-$(CONFIG_SPI_MPC512x_PSC)		+= spi-mpc512x-psc.o
diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c
index 0094c64..378c3c8 100644
--- a/drivers/spi/spi-gpio.c
+++ b/drivers/spi/spi-gpio.c
@@ -22,6 +22,7 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
+#include <linux/delay.h>
 
 #include <linux/spi/spi.h>
 #include <linux/spi/spi_bitbang.h>
@@ -70,6 +71,7 @@
  *		#define	SPI_MOSI_GPIO	120
  *		#define	SPI_SCK_GPIO	121
  *		#define	SPI_N_CHIPSEL	4
+ *		#undef NEED_SPIDELAY
  *		#include "spi-gpio.c"
  */
 
@@ -77,6 +79,7 @@
 #define DRIVER_NAME	"spi_gpio"
 
 #define GENERIC_BITBANG	/* vs tight inlines */
+#define NEED_SPIDELAY	1
 
 /* all functions referencing these symbols must define pdata */
 #define SPI_MISO_GPIO	((pdata)->miso)
@@ -121,12 +124,20 @@
 #undef pdata
 
 /*
- * NOTE:  this clocks "as fast as we can".  It "should" be a function of the
- * requested device clock.  Software overhead means we usually have trouble
- * reaching even one Mbit/sec (except when we can inline bitops), so for now
- * we'll just assume we never need additional per-bit slowdowns.
+ * NOTE:  to clock "as fast as we can", set spi_device.max_speed_hz
+ * and spi_transfer.speed_hz to 0.
+ * Otherwise this is a function of the requested device clock.
+ * Software overhead means we usually have trouble
+ * reaching even one Mbit/sec (except when we can inline bitops). So on small
+ * embedded devices with fast SPI slaves you usually don't need a delay.
  */
-#define spidelay(nsecs)	do {} while (0)
+static inline void spidelay(unsigned nsecs)
+{
+#ifdef NEED_SPIDELAY
+	if (unlikely(nsecs))
+		ndelay(nsecs);
+#endif /* NEED_SPIDELAY */
+}
 
 #include "spi-bitbang-txrx.h"
 
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index b2ccdea..8a31ee2 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -30,6 +30,9 @@
 #include <linux/of_spi.h>
 #include <linux/pm_runtime.h>
 #include <linux/export.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
 
 static void spidev_release(struct device *dev)
 {
@@ -507,6 +510,293 @@
 
 /*-------------------------------------------------------------------------*/
 
+/**
+ * spi_pump_messages - kthread work function which processes spi message queue
+ * @work: pointer to kthread work struct contained in the master struct
+ *
+ * This function checks if there is any spi message in the queue that
+ * needs processing and if so call out to the driver to initialize hardware
+ * and transfer each message.
+ *
+ */
+static void spi_pump_messages(struct kthread_work *work)
+{
+	struct spi_master *master =
+		container_of(work, struct spi_master, pump_messages);
+	unsigned long flags;
+	bool was_busy = false;
+	int ret;
+
+	/* Lock queue and check for queue work */
+	spin_lock_irqsave(&master->queue_lock, flags);
+	if (list_empty(&master->queue) || !master->running) {
+		if (master->busy && master->unprepare_transfer_hardware) {
+			ret = master->unprepare_transfer_hardware(master);
+			if (ret) {
+				dev_err(&master->dev,
+					"failed to unprepare transfer hardware\n");
+				return;
+			}
+		}
+		master->busy = false;
+		spin_unlock_irqrestore(&master->queue_lock, flags);
+		return;
+	}
+
+	/* Make sure we are not already running a message */
+	if (master->cur_msg) {
+		spin_unlock_irqrestore(&master->queue_lock, flags);
+		return;
+	}
+	/* Extract head of queue */
+	master->cur_msg =
+	    list_entry(master->queue.next, struct spi_message, queue);
+
+	list_del_init(&master->cur_msg->queue);
+	if (master->busy)
+		was_busy = true;
+	else
+		master->busy = true;
+	spin_unlock_irqrestore(&master->queue_lock, flags);
+
+	if (!was_busy && master->prepare_transfer_hardware) {
+		ret = master->prepare_transfer_hardware(master);
+		if (ret) {
+			dev_err(&master->dev,
+				"failed to prepare transfer hardware\n");
+			return;
+		}
+	}
+
+	ret = master->transfer_one_message(master, master->cur_msg);
+	if (ret) {
+		dev_err(&master->dev,
+			"failed to transfer one message from queue\n");
+		return;
+	}
+}
+
+static int spi_init_queue(struct spi_master *master)
+{
+	struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 };
+
+	INIT_LIST_HEAD(&master->queue);
+	spin_lock_init(&master->queue_lock);
+
+	master->running = false;
+	master->busy = false;
+
+	init_kthread_worker(&master->kworker);
+	master->kworker_task = kthread_run(kthread_worker_fn,
+					   &master->kworker,
+					   dev_name(&master->dev));
+	if (IS_ERR(master->kworker_task)) {
+		dev_err(&master->dev, "failed to create message pump task\n");
+		return -ENOMEM;
+	}
+	init_kthread_work(&master->pump_messages, spi_pump_messages);
+
+	/*
+	 * Master config will indicate if this controller should run the
+	 * message pump with high (realtime) priority to reduce the transfer
+	 * latency on the bus by minimising the delay between a transfer
+	 * request and the scheduling of the message pump thread. Without this
+	 * setting the message pump thread will remain at default priority.
+	 */
+	if (master->rt) {
+		dev_info(&master->dev,
+			"will run message pump with realtime priority\n");
+		sched_setscheduler(master->kworker_task, SCHED_FIFO, &param);
+	}
+
+	return 0;
+}
+
+/**
+ * spi_get_next_queued_message() - called by driver to check for queued
+ * messages
+ * @master: the master to check for queued messages
+ *
+ * If there are more messages in the queue, the next message is returned from
+ * this call.
+ */
+struct spi_message *spi_get_next_queued_message(struct spi_master *master)
+{
+	struct spi_message *next;
+	unsigned long flags;
+
+	/* get a pointer to the next message, if any */
+	spin_lock_irqsave(&master->queue_lock, flags);
+	if (list_empty(&master->queue))
+		next = NULL;
+	else
+		next = list_entry(master->queue.next,
+				  struct spi_message, queue);
+	spin_unlock_irqrestore(&master->queue_lock, flags);
+
+	return next;
+}
+EXPORT_SYMBOL_GPL(spi_get_next_queued_message);
+
+/**
+ * spi_finalize_current_message() - the current message is complete
+ * @master: the master to return the message to
+ *
+ * Called by the driver to notify the core that the message in the front of the
+ * queue is complete and can be removed from the queue.
+ */
+void spi_finalize_current_message(struct spi_master *master)
+{
+	struct spi_message *mesg;
+	unsigned long flags;
+
+	spin_lock_irqsave(&master->queue_lock, flags);
+	mesg = master->cur_msg;
+	master->cur_msg = NULL;
+
+	queue_kthread_work(&master->kworker, &master->pump_messages);
+	spin_unlock_irqrestore(&master->queue_lock, flags);
+
+	mesg->state = NULL;
+	if (mesg->complete)
+		mesg->complete(mesg->context);
+}
+EXPORT_SYMBOL_GPL(spi_finalize_current_message);
+
+static int spi_start_queue(struct spi_master *master)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&master->queue_lock, flags);
+
+	if (master->running || master->busy) {
+		spin_unlock_irqrestore(&master->queue_lock, flags);
+		return -EBUSY;
+	}
+
+	master->running = true;
+	master->cur_msg = NULL;
+	spin_unlock_irqrestore(&master->queue_lock, flags);
+
+	queue_kthread_work(&master->kworker, &master->pump_messages);
+
+	return 0;
+}
+
+static int spi_stop_queue(struct spi_master *master)
+{
+	unsigned long flags;
+	unsigned limit = 500;
+	int ret = 0;
+
+	spin_lock_irqsave(&master->queue_lock, flags);
+
+	/*
+	 * This is a bit lame, but is optimized for the common execution path.
+	 * A wait_queue on the master->busy could be used, but then the common
+	 * execution path (pump_messages) would be required to call wake_up or
+	 * friends on every SPI message. Do this instead.
+	 */
+	while ((!list_empty(&master->queue) || master->busy) && limit--) {
+		spin_unlock_irqrestore(&master->queue_lock, flags);
+		msleep(10);
+		spin_lock_irqsave(&master->queue_lock, flags);
+	}
+
+	if (!list_empty(&master->queue) || master->busy)
+		ret = -EBUSY;
+	else
+		master->running = false;
+
+	spin_unlock_irqrestore(&master->queue_lock, flags);
+
+	if (ret) {
+		dev_warn(&master->dev,
+			 "could not stop message queue\n");
+		return ret;
+	}
+	return ret;
+}
+
+static int spi_destroy_queue(struct spi_master *master)
+{
+	int ret;
+
+	ret = spi_stop_queue(master);
+
+	/*
+	 * flush_kthread_worker will block until all work is done.
+	 * If the reason that stop_queue timed out is that the work will never
+	 * finish, then it does no good to call flush/stop thread, so
+	 * return anyway.
+	 */
+	if (ret) {
+		dev_err(&master->dev, "problem destroying queue\n");
+		return ret;
+	}
+
+	flush_kthread_worker(&master->kworker);
+	kthread_stop(master->kworker_task);
+
+	return 0;
+}
+
+/**
+ * spi_queued_transfer - transfer function for queued transfers
+ * @spi: spi device which is requesting transfer
+ * @msg: spi message which is to handled is queued to driver queue
+ */
+static int spi_queued_transfer(struct spi_device *spi, struct spi_message *msg)
+{
+	struct spi_master *master = spi->master;
+	unsigned long flags;
+
+	spin_lock_irqsave(&master->queue_lock, flags);
+
+	if (!master->running) {
+		spin_unlock_irqrestore(&master->queue_lock, flags);
+		return -ESHUTDOWN;
+	}
+	msg->actual_length = 0;
+	msg->status = -EINPROGRESS;
+
+	list_add_tail(&msg->queue, &master->queue);
+	if (master->running && !master->busy)
+		queue_kthread_work(&master->kworker, &master->pump_messages);
+
+	spin_unlock_irqrestore(&master->queue_lock, flags);
+	return 0;
+}
+
+static int spi_master_initialize_queue(struct spi_master *master)
+{
+	int ret;
+
+	master->queued = true;
+	master->transfer = spi_queued_transfer;
+
+	/* Initialize and start queue */
+	ret = spi_init_queue(master);
+	if (ret) {
+		dev_err(&master->dev, "problem initializing queue\n");
+		goto err_init_queue;
+	}
+	ret = spi_start_queue(master);
+	if (ret) {
+		dev_err(&master->dev, "problem starting queue\n");
+		goto err_start_queue;
+	}
+
+	return 0;
+
+err_start_queue:
+err_init_queue:
+	spi_destroy_queue(master);
+	return ret;
+}
+
+/*-------------------------------------------------------------------------*/
+
 static void spi_master_release(struct device *dev)
 {
 	struct spi_master *master;
@@ -522,6 +812,7 @@
 };
 
 
+
 /**
  * spi_alloc_master - allocate SPI master controller
  * @dev: the controller, possibly using the platform_bus
@@ -621,6 +912,15 @@
 	dev_dbg(dev, "registered master %s%s\n", dev_name(&master->dev),
 			dynamic ? " (dynamic)" : "");
 
+	/* If we're using a queued driver, start the queue */
+	if (!master->transfer) {
+		status = spi_master_initialize_queue(master);
+		if (status) {
+			device_unregister(&master->dev);
+			goto done;
+		}
+	}
+
 	mutex_lock(&board_lock);
 	list_add_tail(&master->list, &spi_master_list);
 	list_for_each_entry(bi, &board_list, list)
@@ -636,7 +936,6 @@
 }
 EXPORT_SYMBOL_GPL(spi_register_master);
 
-
 static int __unregister(struct device *dev, void *null)
 {
 	spi_unregister_device(to_spi_device(dev));
@@ -657,6 +956,11 @@
 {
 	int dummy;
 
+	if (master->queued) {
+		if (spi_destroy_queue(master))
+			dev_err(&master->dev, "queue remove failed\n");
+	}
+
 	mutex_lock(&board_lock);
 	list_del(&master->list);
 	mutex_unlock(&board_lock);
@@ -666,6 +970,37 @@
 }
 EXPORT_SYMBOL_GPL(spi_unregister_master);
 
+int spi_master_suspend(struct spi_master *master)
+{
+	int ret;
+
+	/* Basically no-ops for non-queued masters */
+	if (!master->queued)
+		return 0;
+
+	ret = spi_stop_queue(master);
+	if (ret)
+		dev_err(&master->dev, "queue stop failed\n");
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(spi_master_suspend);
+
+int spi_master_resume(struct spi_master *master)
+{
+	int ret;
+
+	if (!master->queued)
+		return 0;
+
+	ret = spi_start_queue(master);
+	if (ret)
+		dev_err(&master->dev, "queue restart failed\n");
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(spi_master_resume);
+
 static int __spi_master_match(struct device *dev, void *data)
 {
 	struct spi_master *m;
diff --git a/drivers/spi/spi_gpio_old.c b/drivers/spi/spi_gpio_old.c
new file mode 100644
index 0000000..70545fd
--- /dev/null
+++ b/drivers/spi/spi_gpio_old.c
@@ -0,0 +1,251 @@
+/*
+ * Bitbanging SPI bus driver using GPIO API
+ *
+ * Copyright (c) 2008 Piotr Skamruk
+ * Copyright (c) 2008 Michael Buesch
+ *
+ * based on spi_s3c2410_gpio.c
+ *   Copyright (c) 2006 Ben Dooks
+ *   Copyright (c) 2006 Simtec Electronics
+ * and on i2c-gpio.c
+ *   Copyright (C) 2007 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+#include <linux/spi/spi_gpio_old.h>
+#include <linux/gpio.h>
+#include <asm/atomic.h>
+
+
+struct spi_gpio {
+	struct spi_bitbang bitbang;
+	struct spi_gpio_platform_data *info;
+	struct platform_device *pdev;
+	struct spi_board_info bi;
+};
+
+
+static inline struct spi_gpio *spidev_to_sg(struct spi_device *dev)
+{
+	return dev->controller_data;
+}
+
+static inline void setsck(struct spi_device *dev, int val)
+{
+	struct spi_gpio *sp = spidev_to_sg(dev);
+	gpio_set_value(sp->info->pin_clk, val ? 1 : 0);
+}
+
+static inline void setmosi(struct spi_device *dev, int val)
+{
+	struct spi_gpio *sp = spidev_to_sg(dev);
+	gpio_set_value(sp->info->pin_mosi, val ? 1 : 0);
+}
+
+static inline u32 getmiso(struct spi_device *dev)
+{
+	struct spi_gpio *sp = spidev_to_sg(dev);
+	return gpio_get_value(sp->info->pin_miso) ? 1 : 0;
+}
+
+static inline void do_spidelay(struct spi_device *dev, unsigned nsecs)
+{
+	struct spi_gpio *sp = spidev_to_sg(dev);
+
+	if (!sp->info->no_spi_delay)
+		ndelay(nsecs);
+}
+
+#define spidelay(nsecs) do {					\
+	/* Steal the spi_device pointer from our caller.	\
+	 * The bitbang-API should probably get fixed here... */	\
+	do_spidelay(spi, nsecs);				\
+  } while (0)
+
+#define EXPAND_BITBANG_TXRX
+#include "spi-bitbang-txrx.h"
+
+static u32 spi_gpio_txrx_mode0(struct spi_device *spi,
+			       unsigned nsecs, u32 word, u8 bits)
+{
+	return bitbang_txrx_be_cpha0(spi, nsecs, 0, 0, word, bits);
+}
+
+static u32 spi_gpio_txrx_mode1(struct spi_device *spi,
+			       unsigned nsecs, u32 word, u8 bits)
+{
+	return bitbang_txrx_be_cpha1(spi, nsecs, 0, 0, word, bits);
+}
+
+static u32 spi_gpio_txrx_mode2(struct spi_device *spi,
+			       unsigned nsecs, u32 word, u8 bits)
+{
+	return bitbang_txrx_be_cpha0(spi, nsecs, 1, 0, word, bits);
+}
+
+static u32 spi_gpio_txrx_mode3(struct spi_device *spi,
+			       unsigned nsecs, u32 word, u8 bits)
+{
+	return bitbang_txrx_be_cpha1(spi, nsecs, 1, 0, word, bits);
+}
+
+static void spi_gpio_chipselect(struct spi_device *dev, int on)
+{
+	struct spi_gpio *sp = spidev_to_sg(dev);
+
+	if (sp->info->cs_activelow)
+		on = !on;
+	gpio_set_value(sp->info->pin_cs, on ? 1 : 0);
+}
+
+static int spi_gpio_probe(struct platform_device *pdev)
+{
+	struct spi_master *master;
+	struct spi_gpio_platform_data *pdata;
+	struct spi_gpio *sp;
+	struct spi_device *spidev;
+	int err;
+
+	pdata = pdev->dev.platform_data;
+	if (!pdata)
+		return -ENXIO;
+
+	err = -ENOMEM;
+	master = spi_alloc_master(&pdev->dev, sizeof(struct spi_gpio));
+	if (!master)
+		goto err_alloc_master;
+
+	sp = spi_master_get_devdata(master);
+	platform_set_drvdata(pdev, sp);
+	sp->info = pdata;
+
+	err = gpio_request(pdata->pin_clk, "spi_clock");
+	if (err)
+		goto err_request_clk;
+	err = gpio_request(pdata->pin_mosi, "spi_mosi");
+	if (err)
+		goto err_request_mosi;
+	err = gpio_request(pdata->pin_miso, "spi_miso");
+	if (err)
+		goto err_request_miso;
+	err = gpio_request(pdata->pin_cs, "spi_cs");
+	if (err)
+		goto err_request_cs;
+
+	sp->bitbang.master = spi_master_get(master);
+	sp->bitbang.master->bus_num = -1;
+	sp->bitbang.master->num_chipselect = 1;
+	sp->bitbang.chipselect = spi_gpio_chipselect;
+	sp->bitbang.txrx_word[SPI_MODE_0] = spi_gpio_txrx_mode0;
+	sp->bitbang.txrx_word[SPI_MODE_1] = spi_gpio_txrx_mode1;
+	sp->bitbang.txrx_word[SPI_MODE_2] = spi_gpio_txrx_mode2;
+	sp->bitbang.txrx_word[SPI_MODE_3] = spi_gpio_txrx_mode3;
+
+	gpio_direction_output(pdata->pin_clk, 0);
+	gpio_direction_output(pdata->pin_mosi, 0);
+	gpio_direction_output(pdata->pin_cs,
+			      pdata->cs_activelow ? 1 : 0);
+	gpio_direction_input(pdata->pin_miso);
+
+	err = spi_bitbang_start(&sp->bitbang);
+	if (err)
+		goto err_no_bitbang;
+	err = pdata->boardinfo_setup(&sp->bi, master,
+				     pdata->boardinfo_setup_data);
+	if (err)
+		goto err_bi_setup;
+	sp->bi.controller_data = sp;
+	spidev = spi_new_device(master, &sp->bi);
+	if (!spidev)
+		goto err_new_dev;
+
+	return 0;
+
+err_new_dev:
+err_bi_setup:
+	spi_bitbang_stop(&sp->bitbang);
+err_no_bitbang:
+	spi_master_put(sp->bitbang.master);
+	gpio_free(pdata->pin_cs);
+err_request_cs:
+	gpio_free(pdata->pin_miso);
+err_request_miso:
+	gpio_free(pdata->pin_mosi);
+err_request_mosi:
+	gpio_free(pdata->pin_clk);
+err_request_clk:
+	kfree(master);
+
+err_alloc_master:
+	return err;
+}
+
+static int __devexit spi_gpio_remove(struct platform_device *pdev)
+{
+	struct spi_gpio *sp;
+	struct spi_gpio_platform_data *pdata;
+
+	pdata = pdev->dev.platform_data;
+	sp = platform_get_drvdata(pdev);
+
+	gpio_free(pdata->pin_clk);
+	gpio_free(pdata->pin_mosi);
+	gpio_free(pdata->pin_miso);
+	gpio_free(pdata->pin_cs);
+	spi_bitbang_stop(&sp->bitbang);
+	spi_master_put(sp->bitbang.master);
+
+	return 0;
+}
+
+static struct platform_driver spi_gpio_driver = {
+	.driver		= {
+		.name	= SPI_GPIO_PLATDEV_NAME,
+		.owner	= THIS_MODULE,
+	},
+	.probe		= spi_gpio_probe,
+	.remove		= __devexit_p(spi_gpio_remove),
+};
+
+int spi_gpio_next_id(void)
+{
+	static atomic_t counter = ATOMIC_INIT(-1);
+
+	return atomic_inc_return(&counter);
+}
+EXPORT_SYMBOL(spi_gpio_next_id);
+
+static int __init spi_gpio_init(void)
+{
+	int err;
+
+	err = platform_driver_register(&spi_gpio_driver);
+	if (err)
+		printk(KERN_ERR "spi-gpio: register failed: %d\n", err);
+
+	return err;
+}
+module_init(spi_gpio_init);
+
+static void __exit spi_gpio_exit(void)
+{
+	platform_driver_unregister(&spi_gpio_driver);
+}
+module_exit(spi_gpio_exit);
+
+MODULE_AUTHOR("Piot Skamruk <piotr.skamruk at gmail.com>");
+MODULE_AUTHOR("Michael Buesch");
+MODULE_DESCRIPTION("Platform independent GPIO bitbanging SPI driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/ssb/Kconfig b/drivers/ssb/Kconfig
index 42cdaa9..b8ef7a6 100644
--- a/drivers/ssb/Kconfig
+++ b/drivers/ssb/Kconfig
@@ -29,6 +29,7 @@
 config SSB_BLOCKIO
 	bool
 	depends on SSB
+	default y
 
 config SSB_PCIHOST_POSSIBLE
 	bool
@@ -49,7 +50,7 @@
 config SSB_B43_PCI_BRIDGE
 	bool
 	depends on SSB_PCIHOST
-	default n
+	default y
 
 config SSB_PCMCIAHOST_POSSIBLE
 	bool
diff --git a/drivers/ssb/b43_pci_bridge.c b/drivers/ssb/b43_pci_bridge.c
index bad7ba5..266aa16 100644
--- a/drivers/ssb/b43_pci_bridge.c
+++ b/drivers/ssb/b43_pci_bridge.c
@@ -29,11 +29,14 @@
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4319) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4320) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4321) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4322) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43222) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4324) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4325) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4328) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4329) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x432b) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x432c) },
 	{ 0, },
 };
 MODULE_DEVICE_TABLE(pci, b43_pci_bridge_tbl);
diff --git a/drivers/ssb/driver_chipcommon_pmu.c b/drivers/ssb/driver_chipcommon_pmu.c
index e5a2e0e..b58fef7 100644
--- a/drivers/ssb/driver_chipcommon_pmu.c
+++ b/drivers/ssb/driver_chipcommon_pmu.c
@@ -13,6 +13,9 @@
 #include <linux/ssb/ssb_driver_chipcommon.h>
 #include <linux/delay.h>
 #include <linux/export.h>
+#ifdef CONFIG_BCM47XX
+#include <asm/mach-bcm47xx/nvram.h>
+#endif
 
 #include "ssb_private.h"
 
@@ -92,10 +95,6 @@
 	u32 pmuctl, tmp, pllctl;
 	unsigned int i;
 
-	if ((bus->chip_id == 0x5354) && !crystalfreq) {
-		/* The 5354 crystal freq is 25MHz */
-		crystalfreq = 25000;
-	}
 	if (crystalfreq)
 		e = pmu0_plltab_find_entry(crystalfreq);
 	if (!e)
@@ -321,7 +320,11 @@
 	u32 crystalfreq = 0; /* in kHz. 0 = keep default freq. */
 
 	if (bus->bustype == SSB_BUSTYPE_SSB) {
-		/* TODO: The user may override the crystal frequency. */
+#ifdef CONFIG_BCM47XX
+		char buf[20];
+		if (nvram_getenv("xtalfreq", buf, sizeof(buf)) >= 0)
+			crystalfreq = simple_strtoul(buf, NULL, 0);
+#endif
 	}
 
 	switch (bus->chip_id) {
@@ -330,7 +333,11 @@
 		ssb_pmu1_pllinit_r0(cc, crystalfreq);
 		break;
 	case 0x4328:
+		ssb_pmu0_pllinit_r0(cc, crystalfreq);
+		break;
 	case 0x5354:
+		if (crystalfreq == 0)
+			crystalfreq = 25000;
 		ssb_pmu0_pllinit_r0(cc, crystalfreq);
 		break;
 	case 0x4322:
@@ -607,3 +614,34 @@
 
 EXPORT_SYMBOL(ssb_pmu_set_ldo_voltage);
 EXPORT_SYMBOL(ssb_pmu_set_ldo_paref);
+
+u32 ssb_pmu_get_cpu_clock(struct ssb_chipcommon *cc)
+{
+	struct ssb_bus *bus = cc->dev->bus;
+
+	switch (bus->chip_id) {
+	case 0x5354:
+		/* 5354 chip uses a non programmable PLL of frequency 240MHz */
+		return 240000000;
+	default:
+		ssb_printk(KERN_ERR PFX
+			   "ERROR: PMU cpu clock unknown for device %04X\n",
+			   bus->chip_id);
+		return 0;
+	}
+}
+
+u32 ssb_pmu_get_controlclock(struct ssb_chipcommon *cc)
+{
+	struct ssb_bus *bus = cc->dev->bus;
+
+	switch (bus->chip_id) {
+	case 0x5354:
+		return 120000000;
+	default:
+		ssb_printk(KERN_ERR PFX
+			   "ERROR: PMU controlclock unknown for device %04X\n",
+			   bus->chip_id);
+		return 0;
+	}
+}
diff --git a/drivers/ssb/driver_mipscore.c b/drivers/ssb/driver_mipscore.c
index ced5015..7e2ddc0 100644
--- a/drivers/ssb/driver_mipscore.c
+++ b/drivers/ssb/driver_mipscore.c
@@ -208,6 +208,9 @@
 	struct ssb_bus *bus = mcore->dev->bus;
 	u32 pll_type, n, m, rate = 0;
 
+	if (bus->chipco.capabilities & SSB_CHIPCO_CAP_PMU)
+		return ssb_pmu_get_cpu_clock(&bus->chipco);
+
 	if (bus->extif.dev) {
 		ssb_extif_get_clockcontrol(&bus->extif, &pll_type, &n, &m);
 	} else if (bus->chipco.dev) {
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c
index bb6317f..df0f145 100644
--- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c
@@ -140,19 +140,6 @@
 		put_device(dev->dev);
 }
 
-static inline struct ssb_driver *ssb_driver_get(struct ssb_driver *drv)
-{
-	if (drv)
-		get_driver(&drv->drv);
-	return drv;
-}
-
-static inline void ssb_driver_put(struct ssb_driver *drv)
-{
-	if (drv)
-		put_driver(&drv->drv);
-}
-
 static int ssb_device_resume(struct device *dev)
 {
 	struct ssb_device *ssb_dev = dev_to_ssb_dev(dev);
@@ -250,11 +237,9 @@
 			ssb_device_put(sdev);
 			continue;
 		}
-		sdrv = ssb_driver_get(drv_to_ssb_drv(sdev->dev->driver));
-		if (!sdrv || SSB_WARN_ON(!sdrv->remove)) {
-			ssb_device_put(sdev);
+		sdrv = drv_to_ssb_drv(sdev->dev->driver);
+		if (SSB_WARN_ON(!sdrv->remove))
 			continue;
-		}
 		sdrv->remove(sdev);
 		ctx->device_frozen[i] = 1;
 	}
@@ -293,7 +278,6 @@
 				   dev_name(sdev->dev));
 			result = err;
 		}
-		ssb_driver_put(sdrv);
 		ssb_device_put(sdev);
 	}
 
@@ -1094,6 +1078,9 @@
 	u32 plltype;
 	u32 clkctl_n, clkctl_m;
 
+	if (bus->chipco.capabilities & SSB_CHIPCO_CAP_PMU)
+		return ssb_pmu_get_controlclock(&bus->chipco);
+
 	if (ssb_extif_available(&bus->extif))
 		ssb_extif_get_clockcontrol(&bus->extif, &plltype,
 					   &clkctl_n, &clkctl_m);
diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c
index 973223f..e9d9496 100644
--- a/drivers/ssb/pci.c
+++ b/drivers/ssb/pci.c
@@ -178,6 +178,18 @@
 #define SPEX(_outvar, _offset, _mask, _shift) \
 	SPEX16(_outvar, _offset, _mask, _shift)
 
+#define SPEX_ARRAY8(_field, _offset, _mask, _shift)	\
+	do {	\
+		SPEX(_field[0], _offset +  0, _mask, _shift);	\
+		SPEX(_field[1], _offset +  2, _mask, _shift);	\
+		SPEX(_field[2], _offset +  4, _mask, _shift);	\
+		SPEX(_field[3], _offset +  6, _mask, _shift);	\
+		SPEX(_field[4], _offset +  8, _mask, _shift);	\
+		SPEX(_field[5], _offset + 10, _mask, _shift);	\
+		SPEX(_field[6], _offset + 12, _mask, _shift);	\
+		SPEX(_field[7], _offset + 14, _mask, _shift);	\
+	} while (0)
+
 
 static inline u8 ssb_crc8(u8 crc, u8 data)
 {
@@ -331,7 +343,6 @@
 {
 	int i;
 	u16 v;
-	s8 gain;
 	u16 loc[3];
 
 	if (out->revision == 3)			/* rev 3 moved MAC */
@@ -361,8 +372,9 @@
 	SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14);
 	SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15);
 	SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0);
-	SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE,
-	     SSB_SPROM1_BINF_CCODE_SHIFT);
+	if (out->revision == 1)
+		SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE,
+		     SSB_SPROM1_BINF_CCODE_SHIFT);
 	SPEX(ant_available_a, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTA,
 	     SSB_SPROM1_BINF_ANTA_SHIFT);
 	SPEX(ant_available_bg, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTBG,
@@ -388,22 +400,16 @@
 	SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0);
 	if (out->revision >= 2)
 		SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0);
+	SPEX(alpha2[0], SSB_SPROM1_CCODE, 0xff00, 8);
+	SPEX(alpha2[1], SSB_SPROM1_CCODE, 0x00ff, 0);
 
 	/* Extract the antenna gain values. */
-	gain = r123_extract_antgain(out->revision, in,
-				    SSB_SPROM1_AGAIN_BG,
-				    SSB_SPROM1_AGAIN_BG_SHIFT);
-	out->antenna_gain.ghz24.a0 = gain;
-	out->antenna_gain.ghz24.a1 = gain;
-	out->antenna_gain.ghz24.a2 = gain;
-	out->antenna_gain.ghz24.a3 = gain;
-	gain = r123_extract_antgain(out->revision, in,
-				    SSB_SPROM1_AGAIN_A,
-				    SSB_SPROM1_AGAIN_A_SHIFT);
-	out->antenna_gain.ghz5.a0 = gain;
-	out->antenna_gain.ghz5.a1 = gain;
-	out->antenna_gain.ghz5.a2 = gain;
-	out->antenna_gain.ghz5.a3 = gain;
+	out->antenna_gain.a0 = r123_extract_antgain(out->revision, in,
+						    SSB_SPROM1_AGAIN_BG,
+						    SSB_SPROM1_AGAIN_BG_SHIFT);
+	out->antenna_gain.a1 = r123_extract_antgain(out->revision, in,
+						    SSB_SPROM1_AGAIN_A,
+						    SSB_SPROM1_AGAIN_A_SHIFT);
 }
 
 /* Revs 4 5 and 8 have partially shared layout */
@@ -464,14 +470,17 @@
 	SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0);
 	SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A,
 	     SSB_SPROM4_ETHPHY_ET1A_SHIFT);
+	SPEX(board_rev, SSB_SPROM4_BOARDREV, 0xFFFF, 0);
 	if (out->revision == 4) {
-		SPEX(country_code, SSB_SPROM4_CCODE, 0xFFFF, 0);
+		SPEX(alpha2[0], SSB_SPROM4_CCODE, 0xff00, 8);
+		SPEX(alpha2[1], SSB_SPROM4_CCODE, 0x00ff, 0);
 		SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0);
 		SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0);
 		SPEX(boardflags2_lo, SSB_SPROM4_BFL2LO, 0xFFFF, 0);
 		SPEX(boardflags2_hi, SSB_SPROM4_BFL2HI, 0xFFFF, 0);
 	} else {
-		SPEX(country_code, SSB_SPROM5_CCODE, 0xFFFF, 0);
+		SPEX(alpha2[0], SSB_SPROM5_CCODE, 0xff00, 8);
+		SPEX(alpha2[1], SSB_SPROM5_CCODE, 0x00ff, 0);
 		SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0);
 		SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0);
 		SPEX(boardflags2_lo, SSB_SPROM5_BFL2LO, 0xFFFF, 0);
@@ -504,16 +513,14 @@
 	}
 
 	/* Extract the antenna gain values. */
-	SPEX(antenna_gain.ghz24.a0, SSB_SPROM4_AGAIN01,
+	SPEX(antenna_gain.a0, SSB_SPROM4_AGAIN01,
 	     SSB_SPROM4_AGAIN0, SSB_SPROM4_AGAIN0_SHIFT);
-	SPEX(antenna_gain.ghz24.a1, SSB_SPROM4_AGAIN01,
+	SPEX(antenna_gain.a1, SSB_SPROM4_AGAIN01,
 	     SSB_SPROM4_AGAIN1, SSB_SPROM4_AGAIN1_SHIFT);
-	SPEX(antenna_gain.ghz24.a2, SSB_SPROM4_AGAIN23,
+	SPEX(antenna_gain.a2, SSB_SPROM4_AGAIN23,
 	     SSB_SPROM4_AGAIN2, SSB_SPROM4_AGAIN2_SHIFT);
-	SPEX(antenna_gain.ghz24.a3, SSB_SPROM4_AGAIN23,
+	SPEX(antenna_gain.a3, SSB_SPROM4_AGAIN23,
 	     SSB_SPROM4_AGAIN3, SSB_SPROM4_AGAIN3_SHIFT);
-	memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24,
-	       sizeof(out->antenna_gain.ghz5));
 
 	sprom_extract_r458(out, in);
 
@@ -523,14 +530,22 @@
 static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
 {
 	int i;
-	u16 v;
+	u16 v, o;
+	u16 pwr_info_offset[] = {
+		SSB_SROM8_PWR_INFO_CORE0, SSB_SROM8_PWR_INFO_CORE1,
+		SSB_SROM8_PWR_INFO_CORE2, SSB_SROM8_PWR_INFO_CORE3
+	};
+	BUILD_BUG_ON(ARRAY_SIZE(pwr_info_offset) !=
+			ARRAY_SIZE(out->core_pwr_info));
 
 	/* extract the MAC address */
 	for (i = 0; i < 3; i++) {
 		v = in[SPOFF(SSB_SPROM8_IL0MAC) + i];
 		*(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
 	}
-	SPEX(country_code, SSB_SPROM8_CCODE, 0xFFFF, 0);
+	SPEX(board_rev, SSB_SPROM8_BOARDREV, 0xFFFF, 0);
+	SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8);
+	SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0);
 	SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0);
 	SPEX(boardflags_hi, SSB_SPROM8_BFLHI, 0xFFFF, 0);
 	SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, 0xFFFF, 0);
@@ -596,16 +611,46 @@
 	SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0);
 
 	/* Extract the antenna gain values. */
-	SPEX(antenna_gain.ghz24.a0, SSB_SPROM8_AGAIN01,
+	SPEX(antenna_gain.a0, SSB_SPROM8_AGAIN01,
 	     SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT);
-	SPEX(antenna_gain.ghz24.a1, SSB_SPROM8_AGAIN01,
+	SPEX(antenna_gain.a1, SSB_SPROM8_AGAIN01,
 	     SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT);
-	SPEX(antenna_gain.ghz24.a2, SSB_SPROM8_AGAIN23,
+	SPEX(antenna_gain.a2, SSB_SPROM8_AGAIN23,
 	     SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT);
-	SPEX(antenna_gain.ghz24.a3, SSB_SPROM8_AGAIN23,
+	SPEX(antenna_gain.a3, SSB_SPROM8_AGAIN23,
 	     SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT);
-	memcpy(&out->antenna_gain.ghz5, &out->antenna_gain.ghz24,
-	       sizeof(out->antenna_gain.ghz5));
+
+	/* Extract cores power info info */
+	for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) {
+		o = pwr_info_offset[i];
+		SPEX(core_pwr_info[i].itssi_2g, o + SSB_SROM8_2G_MAXP_ITSSI,
+			SSB_SPROM8_2G_ITSSI, SSB_SPROM8_2G_ITSSI_SHIFT);
+		SPEX(core_pwr_info[i].maxpwr_2g, o + SSB_SROM8_2G_MAXP_ITSSI,
+			SSB_SPROM8_2G_MAXP, 0);
+
+		SPEX(core_pwr_info[i].pa_2g[0], o + SSB_SROM8_2G_PA_0, ~0, 0);
+		SPEX(core_pwr_info[i].pa_2g[1], o + SSB_SROM8_2G_PA_1, ~0, 0);
+		SPEX(core_pwr_info[i].pa_2g[2], o + SSB_SROM8_2G_PA_2, ~0, 0);
+
+		SPEX(core_pwr_info[i].itssi_5g, o + SSB_SROM8_5G_MAXP_ITSSI,
+			SSB_SPROM8_5G_ITSSI, SSB_SPROM8_5G_ITSSI_SHIFT);
+		SPEX(core_pwr_info[i].maxpwr_5g, o + SSB_SROM8_5G_MAXP_ITSSI,
+			SSB_SPROM8_5G_MAXP, 0);
+		SPEX(core_pwr_info[i].maxpwr_5gh, o + SSB_SPROM8_5GHL_MAXP,
+			SSB_SPROM8_5GH_MAXP, 0);
+		SPEX(core_pwr_info[i].maxpwr_5gl, o + SSB_SPROM8_5GHL_MAXP,
+			SSB_SPROM8_5GL_MAXP, SSB_SPROM8_5GL_MAXP_SHIFT);
+
+		SPEX(core_pwr_info[i].pa_5gl[0], o + SSB_SROM8_5GL_PA_0, ~0, 0);
+		SPEX(core_pwr_info[i].pa_5gl[1], o + SSB_SROM8_5GL_PA_1, ~0, 0);
+		SPEX(core_pwr_info[i].pa_5gl[2], o + SSB_SROM8_5GL_PA_2, ~0, 0);
+		SPEX(core_pwr_info[i].pa_5g[0], o + SSB_SROM8_5G_PA_0, ~0, 0);
+		SPEX(core_pwr_info[i].pa_5g[1], o + SSB_SROM8_5G_PA_1, ~0, 0);
+		SPEX(core_pwr_info[i].pa_5g[2], o + SSB_SROM8_5G_PA_2, ~0, 0);
+		SPEX(core_pwr_info[i].pa_5gh[0], o + SSB_SROM8_5GH_PA_0, ~0, 0);
+		SPEX(core_pwr_info[i].pa_5gh[1], o + SSB_SROM8_5GH_PA_1, ~0, 0);
+		SPEX(core_pwr_info[i].pa_5gh[2], o + SSB_SROM8_5GH_PA_2, ~0, 0);
+	}
 
 	/* Extract FEM info */
 	SPEX(fem.ghz2.tssipos, SSB_SPROM8_FEM2G,
@@ -630,6 +675,63 @@
 	SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G,
 		SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT);
 
+	SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON,
+	     SSB_SPROM8_LEDDC_ON_SHIFT);
+	SPEX(leddc_off_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_OFF,
+	     SSB_SPROM8_LEDDC_OFF_SHIFT);
+
+	SPEX(txchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_TXCHAIN,
+	     SSB_SPROM8_TXRXC_TXCHAIN_SHIFT);
+	SPEX(rxchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_RXCHAIN,
+	     SSB_SPROM8_TXRXC_RXCHAIN_SHIFT);
+	SPEX(antswitch, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_SWITCH,
+	     SSB_SPROM8_TXRXC_SWITCH_SHIFT);
+
+	SPEX(opo, SSB_SPROM8_OFDM2GPO, 0x00ff, 0);
+
+	SPEX_ARRAY8(mcs2gpo, SSB_SPROM8_2G_MCSPO, ~0, 0);
+	SPEX_ARRAY8(mcs5gpo, SSB_SPROM8_5G_MCSPO, ~0, 0);
+	SPEX_ARRAY8(mcs5glpo, SSB_SPROM8_5GL_MCSPO, ~0, 0);
+	SPEX_ARRAY8(mcs5ghpo, SSB_SPROM8_5GH_MCSPO, ~0, 0);
+
+	SPEX(rawtempsense, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_RAWTEMP,
+	     SSB_SPROM8_RAWTS_RAWTEMP_SHIFT);
+	SPEX(measpower, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_MEASPOWER,
+	     SSB_SPROM8_RAWTS_MEASPOWER_SHIFT);
+	SPEX(tempsense_slope, SSB_SPROM8_OPT_CORRX,
+	     SSB_SPROM8_OPT_CORRX_TEMP_SLOPE,
+	     SSB_SPROM8_OPT_CORRX_TEMP_SLOPE_SHIFT);
+	SPEX(tempcorrx, SSB_SPROM8_OPT_CORRX, SSB_SPROM8_OPT_CORRX_TEMPCORRX,
+	     SSB_SPROM8_OPT_CORRX_TEMPCORRX_SHIFT);
+	SPEX(tempsense_option, SSB_SPROM8_OPT_CORRX,
+	     SSB_SPROM8_OPT_CORRX_TEMP_OPTION,
+	     SSB_SPROM8_OPT_CORRX_TEMP_OPTION_SHIFT);
+	SPEX(freqoffset_corr, SSB_SPROM8_HWIQ_IQSWP,
+	     SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR,
+	     SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR_SHIFT);
+	SPEX(iqcal_swp_dis, SSB_SPROM8_HWIQ_IQSWP,
+	     SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP,
+	     SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT);
+	SPEX(hw_iqcal_en, SSB_SPROM8_HWIQ_IQSWP, SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL,
+	     SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT);
+
+	SPEX(bw40po, SSB_SPROM8_BW40PO, ~0, 0);
+	SPEX(cddpo, SSB_SPROM8_CDDPO, ~0, 0);
+	SPEX(stbcpo, SSB_SPROM8_STBCPO, ~0, 0);
+	SPEX(bwduppo, SSB_SPROM8_BWDUPPO, ~0, 0);
+
+	SPEX(tempthresh, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_TRESH,
+	     SSB_SPROM8_THERMAL_TRESH_SHIFT);
+	SPEX(tempoffset, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_OFFSET,
+	     SSB_SPROM8_THERMAL_OFFSET_SHIFT);
+	SPEX(phycal_tempdelta, SSB_SPROM8_TEMPDELTA,
+	     SSB_SPROM8_TEMPDELTA_PHYCAL,
+	     SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT);
+	SPEX(temps_period, SSB_SPROM8_TEMPDELTA, SSB_SPROM8_TEMPDELTA_PERIOD,
+	     SSB_SPROM8_TEMPDELTA_PERIOD_SHIFT);
+	SPEX(temps_hysteresis, SSB_SPROM8_TEMPDELTA,
+	     SSB_SPROM8_TEMPDELTA_HYSTERESIS,
+	     SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT);
 	sprom_extract_r458(out, in);
 
 	/* TODO - get remaining rev 8 stuff needed */
@@ -759,7 +861,6 @@
 {
 	bi->vendor = bus->host_pci->subsystem_vendor;
 	bi->type = bus->host_pci->subsystem_device;
-	bi->rev = bus->host_pci->revision;
 }
 
 int ssb_pci_get_invariants(struct ssb_bus *bus,
diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c
index c821c6b..fbafed5 100644
--- a/drivers/ssb/pcmcia.c
+++ b/drivers/ssb/pcmcia.c
@@ -676,14 +676,10 @@
 	case SSB_PCMCIA_CIS_ANTGAIN:
 		GOTO_ERROR_ON(tuple->TupleDataLen != 2,
 			"antg tpl size");
-		sprom->antenna_gain.ghz24.a0 = tuple->TupleData[1];
-		sprom->antenna_gain.ghz24.a1 = tuple->TupleData[1];
-		sprom->antenna_gain.ghz24.a2 = tuple->TupleData[1];
-		sprom->antenna_gain.ghz24.a3 = tuple->TupleData[1];
-		sprom->antenna_gain.ghz5.a0 = tuple->TupleData[1];
-		sprom->antenna_gain.ghz5.a1 = tuple->TupleData[1];
-		sprom->antenna_gain.ghz5.a2 = tuple->TupleData[1];
-		sprom->antenna_gain.ghz5.a3 = tuple->TupleData[1];
+		sprom->antenna_gain.a0 = tuple->TupleData[1];
+		sprom->antenna_gain.a1 = tuple->TupleData[1];
+		sprom->antenna_gain.a2 = tuple->TupleData[1];
+		sprom->antenna_gain.a3 = tuple->TupleData[1];
 		break;
 	case SSB_PCMCIA_CIS_BFLAGS:
 		GOTO_ERROR_ON((tuple->TupleDataLen != 3) &&
diff --git a/drivers/ssb/scan.c b/drivers/ssb/scan.c
index 3e84487..ab4627c 100644
--- a/drivers/ssb/scan.c
+++ b/drivers/ssb/scan.c
@@ -90,6 +90,8 @@
 		return "ARM 1176";
 	case SSB_DEV_ARM_7TDMI:
 		return "ARM 7TDMI";
+	case SSB_DEV_ARM_CM3:
+		return "ARM Cortex M3";
 	}
 	return "UNKNOWN";
 }
@@ -318,6 +320,9 @@
 			bus->chip_package = 0;
 		}
 	}
+	ssb_printk(KERN_INFO PFX "Found chip with id 0x%04X, rev 0x%02X and "
+		   "package 0x%02X\n", bus->chip_id, bus->chip_rev,
+		   bus->chip_package);
 	if (!bus->nr_devices)
 		bus->nr_devices = chipid_to_nrcores(bus->chip_id);
 	if (bus->nr_devices > ARRAY_SIZE(bus->devices)) {
diff --git a/drivers/ssb/sdio.c b/drivers/ssb/sdio.c
index 63fd709..b2d36f7 100644
--- a/drivers/ssb/sdio.c
+++ b/drivers/ssb/sdio.c
@@ -551,14 +551,10 @@
 			case SSB_SDIO_CIS_ANTGAIN:
 				GOTO_ERROR_ON(tuple->size != 2,
 					      "antg tpl size");
-				sprom->antenna_gain.ghz24.a0 = tuple->data[1];
-				sprom->antenna_gain.ghz24.a1 = tuple->data[1];
-				sprom->antenna_gain.ghz24.a2 = tuple->data[1];
-				sprom->antenna_gain.ghz24.a3 = tuple->data[1];
-				sprom->antenna_gain.ghz5.a0 = tuple->data[1];
-				sprom->antenna_gain.ghz5.a1 = tuple->data[1];
-				sprom->antenna_gain.ghz5.a2 = tuple->data[1];
-				sprom->antenna_gain.ghz5.a3 = tuple->data[1];
+				sprom->antenna_gain.a0 = tuple->data[1];
+				sprom->antenna_gain.a1 = tuple->data[1];
+				sprom->antenna_gain.a2 = tuple->data[1];
+				sprom->antenna_gain.a3 = tuple->data[1];
 				break;
 			case SSB_SDIO_CIS_BFLAGS:
 				GOTO_ERROR_ON((tuple->size != 3) &&
diff --git a/drivers/ssb/ssb_private.h b/drivers/ssb/ssb_private.h
index 7765301..a305550 100644
--- a/drivers/ssb/ssb_private.h
+++ b/drivers/ssb/ssb_private.h
@@ -207,4 +207,8 @@
 }
 #endif /* CONFIG_SSB_B43_PCI_BRIDGE */
 
+/* driver_chipcommon_pmu.c */
+extern u32 ssb_pmu_get_cpu_clock(struct ssb_chipcommon *cc);
+extern u32 ssb_pmu_get_controlclock(struct ssb_chipcommon *cc);
+
 #endif /* LINUX_SSB_PRIVATE_H_ */
diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c
index 6cd4143..6579ffd 100644
--- a/drivers/tty/serial/uartlite.c
+++ b/drivers/tty/serial/uartlite.c
@@ -216,8 +216,7 @@
 {
 	int ret;
 
-	ret = request_irq(port->irq, ulite_isr,
-			  IRQF_SHARED | IRQF_SAMPLE_RANDOM, "uartlite", port);
+	ret = request_irq(port->irq, ulite_isr, IRQF_SHARED, "uartlite", port);
 	if (ret)
 		return ret;
 
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index ce5e147..41411c8 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -24,6 +24,7 @@
 #include <linux/kthread.h>
 #include <linux/mutex.h>
 #include <linux/freezer.h>
+#include <linux/random.h>
 
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
@@ -1896,6 +1897,14 @@
 	/* Tell the world! */
 	announce_device(udev);
 
+	if (udev->serial)
+		add_device_randomness(udev->serial, strlen(udev->serial));
+	if (udev->product)
+		add_device_randomness(udev->product, strlen(udev->product));
+	if (udev->manufacturer)
+		add_device_randomness(udev->manufacturer,
+				      strlen(udev->manufacturer));
+
 	device_enable_async_suspend(&udev->dev);
 	/* Register the device.  The device driver is responsible
 	 * for configuring the device and invoking the add-device
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 8ca9f99..457a687 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -652,6 +652,71 @@
 }
 EXPORT_SYMBOL_GPL(__usb_get_extra_descriptor);
 
+static struct usb_device *match_device_name(struct usb_device *dev,
+					    const char *name)
+{
+	struct usb_device *ret_dev = NULL;
+	int child;
+
+	dev_dbg(&dev->dev, "check for name %s ...\n", name);
+
+	/* see if this device matches */
+	if (strcmp(dev_name(&dev->dev), name) == 0 ) {
+		dev_dbg(&dev->dev, "matched this device!\n");
+		ret_dev = usb_get_dev(dev);
+		goto exit;
+	}
+
+	/* look through all of the children of this device */
+	for (child = 0; child < dev->maxchild; ++child) {
+		if (dev->children[child]) {
+			usb_lock_device(dev->children[child]);
+			ret_dev = match_device_name(dev->children[child], name);
+			usb_unlock_device(dev->children[child]);
+			if (ret_dev)
+				goto exit;
+		}
+	}
+exit:
+	return ret_dev;
+}
+
+/**
+ * usb_find_device_by_name - find a specific usb device in the system
+ * @name: the name of the device to find
+ *
+ * Returns a pointer to a struct usb_device if such a specified usb
+ * device is present in the system currently.  The usage count of the
+ * device will be incremented if a device is found.  Make sure to call
+ * usb_put_dev() when the caller is finished with the device.
+ *
+ * If a device with the specified bus id is not found, NULL is returned.
+ */
+struct usb_device *usb_find_device_by_name(const char *name)
+{
+	struct list_head *buslist;
+	struct usb_bus *bus;
+	struct usb_device *dev = NULL;
+
+	mutex_lock(&usb_bus_list_lock);
+	for (buslist = usb_bus_list.next;
+	     buslist != &usb_bus_list;
+	     buslist = buslist->next) {
+		bus = container_of(buslist, struct usb_bus, bus_list);
+		if (!bus->root_hub)
+			continue;
+		usb_lock_device(bus->root_hub);
+		dev = match_device_name(bus->root_hub, name);
+		usb_unlock_device(bus->root_hub);
+		if (dev)
+			goto exit;
+	}
+exit:
+	mutex_unlock(&usb_bus_list_lock);
+	return dev;
+}
+EXPORT_SYMBOL_GPL(usb_find_device_by_name);
+
 /**
  * usb_alloc_coherent - allocate dma-consistent buffer for URB_NO_xxx_DMA_MAP
  * @dev: device the buffer will be used with
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
index 5977749..e7af5a6 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/drivers/usb/gadget/goku_udc.c
@@ -1839,7 +1839,7 @@
 	/* init to known state, then setup irqs */
 	udc_reset(dev);
 	udc_reinit (dev);
-	if (request_irq(pdev->irq, goku_irq, IRQF_SHARED/*|IRQF_SAMPLE_RANDOM*/,
+	if (request_irq(pdev->irq, goku_irq, IRQF_SHARED,
 			driver_name, dev) != 0) {
 		DBG(dev, "request interrupt %d failed\n", pdev->irq);
 		retval = -EBUSY;
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index 7d0835e..3efe544 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -2943,7 +2943,7 @@
 
 	/* USB general purpose IRQ:  ep0, state changes, dma, etc */
 	status = request_irq(pdev->resource[1].start, omap_udc_irq,
-			IRQF_SAMPLE_RANDOM, driver_name, udc);
+			     0, driver_name, udc);
 	if (status != 0) {
 		ERR("can't get irq %d, err %d\n",
 			(int) pdev->resource[1].start, status);
@@ -2952,7 +2952,7 @@
 
 	/* USB "non-iso" IRQ (PIO for all but ep0) */
 	status = request_irq(pdev->resource[2].start, omap_udc_pio_irq,
-			IRQF_SAMPLE_RANDOM, "omap_udc pio", udc);
+			     0, "omap_udc pio", udc);
 	if (status != 0) {
 		ERR("can't get irq %d, err %d\n",
 			(int) pdev->resource[2].start, status);
diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c
index 33adf38..3d2e988 100644
--- a/drivers/usb/gadget/pxa25x_udc.c
+++ b/drivers/usb/gadget/pxa25x_udc.c
@@ -2202,19 +2202,15 @@
 
 #ifdef CONFIG_ARCH_LUBBOCK
 	if (machine_is_lubbock()) {
-		retval = request_irq(LUBBOCK_USB_DISC_IRQ,
-				lubbock_vbus_irq,
-				IRQF_SAMPLE_RANDOM,
-				driver_name, dev);
+		retval = request_irq(LUBBOCK_USB_DISC_IRQ, lubbock_vbus_irq,
+				     0, driver_name, dev);
 		if (retval != 0) {
 			pr_err("%s: can't get irq %i, err %d\n",
 				driver_name, LUBBOCK_USB_DISC_IRQ, retval);
 			goto err_irq_lub;
 		}
-		retval = request_irq(LUBBOCK_USB_IRQ,
-				lubbock_vbus_irq,
-				IRQF_SAMPLE_RANDOM,
-				driver_name, dev);
+		retval = request_irq(LUBBOCK_USB_IRQ, lubbock_vbus_irq,
+				     0, driver_name, dev);
 		if (retval != 0) {
 			pr_err("%s: can't get irq %i, err %d\n",
 				driver_name, LUBBOCK_USB_IRQ, retval);
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index e5b3aed..8b80ea6 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -795,7 +795,7 @@
 		"USB %x.%x started, EHCI %x.%02x%s\n",
 		((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f),
 		temp >> 8, temp & 0xff,
-		ignore_oc ? ", overcurrent ignored" : "");
+		(ignore_oc || ehci->ignore_oc) ? ", overcurrent ignored" : "");
 
 	ehci_writel(ehci, INTR_MASK,
 		    &ehci->regs->intr_enable); /* Turn On Interrupts */
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 77bbb23..c39ea4a 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -578,7 +578,7 @@
 	 * always set, seem to clear PORT_OCC and PORT_CSC when writing to
 	 * PORT_POWER; that's surprising, but maybe within-spec.
 	 */
-	if (!ignore_oc)
+	if (!ignore_oc && !ehci->ignore_oc)
 		mask = PORT_CSC | PORT_PEC | PORT_OCC;
 	else
 		mask = PORT_CSC | PORT_PEC;
@@ -803,7 +803,7 @@
 		if (temp & PORT_PEC)
 			status |= USB_PORT_STAT_C_ENABLE << 16;
 
-		if ((temp & PORT_OCC) && !ignore_oc){
+		if ((temp & PORT_OCC) && (!ignore_oc && !ehci->ignore_oc)){
 			status |= USB_PORT_STAT_C_OVERCURRENT << 16;
 
 			/*
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 0a5fda7..dcf60f5 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -147,6 +147,7 @@
 	unsigned		use_dummy_qh:1;	/* AMD Frame List table quirk*/
 	unsigned		has_synopsys_hc_bug:1; /* Synopsys HC */
 	unsigned		frame_index_bug:1; /* MosChip (AKA NetMos) */
+	unsigned		ignore_oc:1;
 
 	/* required for usb32 quirk */
 	#define OHCI_CTRL_HCFS          (3 << 6)
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index 833b3c6..75344ff 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -432,6 +432,8 @@
 }
 EXPORT_SYMBOL_GPL(uhci_check_and_reset_hc);
 
+#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS
+
 static inline int io_type_enabled(struct pci_dev *pdev, unsigned int mask)
 {
 	u16 cmd;
@@ -928,3 +930,5 @@
 	pci_disable_device(pdev);
 }
 DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, quirk_usb_early_handoff);
+
+#endif
diff --git a/drivers/usb/host/pci-quirks.h b/drivers/usb/host/pci-quirks.h
index b1002a8..442196c 100644
--- a/drivers/usb/host/pci-quirks.h
+++ b/drivers/usb/host/pci-quirks.h
@@ -8,9 +8,17 @@
 void usb_amd_dev_put(void);
 void usb_amd_quirk_pll_disable(void);
 void usb_amd_quirk_pll_enable(void);
+#if !defined(CONFIG_PCI_DISABLE_COMMON_QUIRKS)
 bool usb_is_intel_switchable_xhci(struct pci_dev *pdev);
 void usb_enable_xhci_ports(struct pci_dev *xhci_pdev);
 #else
+static inline bool usb_is_intel_switchable_xhci(struct pci_dev *pdev)
+{
+	return false;
+}
+static inline void usb_enable_xhci_ports(struct pci_dev *xhci_pdev) {}
+#endif
+#else
 static inline void usb_amd_quirk_pll_disable(void) {}
 static inline void usb_amd_quirk_pll_enable(void) {}
 static inline void usb_amd_dev_put(void) {}
diff --git a/drivers/usb/otg/gpio_vbus.c b/drivers/usb/otg/gpio_vbus.c
index fb644c1..80043e0 100644
--- a/drivers/usb/otg/gpio_vbus.c
+++ b/drivers/usb/otg/gpio_vbus.c
@@ -51,8 +51,7 @@
  * edges might be workable.
  */
 #define VBUS_IRQ_FLAGS \
-	( IRQF_SAMPLE_RANDOM | IRQF_SHARED \
-	| IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING )
+	( IRQF_SHARED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING )
 
 
 /* interface to regulator framework */
@@ -253,7 +252,7 @@
 	if (res) {
 		irq = res->start;
 		res->flags &= IRQF_TRIGGER_MASK;
-		res->flags |= IRQF_SAMPLE_RANDOM | IRQF_SHARED;
+		res->flags |= IRQF_SHARED;
 	} else
 		irq = gpio_to_irq(gpio);
 
diff --git a/drivers/usb/otg/isp1301_omap.c b/drivers/usb/otg/isp1301_omap.c
index 8c86787..9b5b181 100644
--- a/drivers/usb/otg/isp1301_omap.c
+++ b/drivers/usb/otg/isp1301_omap.c
@@ -1567,7 +1567,6 @@
 		isp->irq_type = IRQF_TRIGGER_FALLING;
 	}
 
-	isp->irq_type |= IRQF_SAMPLE_RANDOM;
 	status = request_irq(i2c->irq, isp1301_irq,
 			isp->irq_type, DRIVER_NAME, isp);
 	if (status < 0) {
diff --git a/drivers/watchdog/mpcore_wdt.c b/drivers/watchdog/mpcore_wdt.c
index 82ccd36..7aa4a4e 100644
--- a/drivers/watchdog/mpcore_wdt.c
+++ b/drivers/watchdog/mpcore_wdt.c
@@ -99,9 +99,7 @@
 
 	spin_lock(&wdt_lock);
 	/* Assume prescale is set to 256 */
-	count =  __raw_readl(wdt->base + TWD_WDOG_COUNTER);
-	count = (0xFFFFFFFFU - count) * (HZ / 5);
-	count = (count / 256) * mpcore_margin;
+	count = (twd_timer_get_rate() / 256) * mpcore_margin;
 
 	/* Reload the counter */
 	writel(count + wdt->perturb, wdt->base + TWD_WDOG_LOAD);
@@ -120,18 +118,25 @@
 
 static void mpcore_wdt_start(struct mpcore_wdt *wdt)
 {
+	u32 mode;
+
 	dev_printk(KERN_INFO, wdt->dev, "enabling watchdog.\n");
 
 	/* This loads the count register but does NOT start the count yet */
 	mpcore_wdt_keepalive(wdt);
 
+	/* Setup watchdog - prescale=256, enable=1 */
+	mode = (255 << 8) | TWD_WDOG_CONTROL_ENABLE;
+
 	if (mpcore_noboot) {
-		/* Enable watchdog - prescale=256, watchdog mode=0, enable=1 */
-		writel(0x0000FF01, wdt->base + TWD_WDOG_CONTROL);
+		/* timer mode, send interrupt */
+		mode |=	TWD_WDOG_CONTROL_TIMER_MODE |
+				TWD_WDOG_CONTROL_IT_ENABLE;
 	} else {
-		/* Enable watchdog - prescale=256, watchdog mode=1, enable=1 */
-		writel(0x0000FF09, wdt->base + TWD_WDOG_CONTROL);
+		/* watchdog mode */
+		mode |=	TWD_WDOG_CONTROL_WATCHDOG_MODE;
 	}
+	writel(mode, wdt->base + TWD_WDOG_CONTROL);
 }
 
 static int mpcore_wdt_set_heartbeat(int t)
@@ -235,7 +240,8 @@
 	if (_IOC_DIR(cmd) && _IOC_SIZE(cmd) > sizeof(uarg))
 		return -ENOTTY;
 
-	if (_IOC_DIR(cmd) & _IOC_WRITE) {
+	if ((_IOC_DIR(cmd) & _IOC_WRITE)
+			|| cmd == WDIOC_SETOPTIONS) {
 		ret = copy_from_user(&uarg, (void __user *)arg, _IOC_SIZE(cmd));
 		if (ret)
 			return -EFAULT;
diff --git a/fs/Kconfig b/fs/Kconfig
index d621f02..f4193c9 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -35,6 +35,7 @@
 source "fs/ocfs2/Kconfig"
 source "fs/btrfs/Kconfig"
 source "fs/nilfs2/Kconfig"
+source "fs/yaffs2/Kconfig"
 
 endif # BLOCK
 
@@ -63,6 +64,7 @@
 
 source "fs/autofs4/Kconfig"
 source "fs/fuse/Kconfig"
+source "fs/overlayfs/Kconfig"
 
 config CUSE
 	tristate "Character device in Userspace support"
diff --git a/fs/Makefile b/fs/Makefile
index 93804d4..b24bf71 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -105,6 +105,7 @@
 obj-$(CONFIG_AUTOFS4_FS)	+= autofs4/
 obj-$(CONFIG_ADFS_FS)		+= adfs/
 obj-$(CONFIG_FUSE_FS)		+= fuse/
+obj-$(CONFIG_OVERLAYFS_FS)	+= overlayfs/
 obj-$(CONFIG_UDF_FS)		+= udf/
 obj-$(CONFIG_SUN_OPENPROMFS)	+= openpromfs/
 obj-$(CONFIG_OMFS_FS)		+= omfs/
@@ -124,3 +125,5 @@
 obj-y				+= exofs/ # Multiple modules
 obj-$(CONFIG_CEPH_FS)		+= ceph/
 obj-$(CONFIG_PSTORE)		+= pstore/
+obj-$(CONFIG_YAFFS_FS)		+= yaffs2/
+
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index b4a6bef..703cda3 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -544,6 +544,13 @@
 	s->s_maxbytes = path.dentry->d_sb->s_maxbytes;
 	s->s_blocksize = path.dentry->d_sb->s_blocksize;
 	s->s_magic = ECRYPTFS_SUPER_MAGIC;
+	s->s_stack_depth = path.dentry->d_sb->s_stack_depth + 1;
+
+	rc = -EINVAL;
+	if (s->s_stack_depth > FILESYSTEM_MAX_STACK_DEPTH) {
+		printk(KERN_ERR "eCryptfs: maximum fs stacking depth exceeded\n");
+		goto out_free;
+	}
 
 	inode = ecryptfs_get_inode(path.dentry->d_inode, s);
 	rc = PTR_ERR(inode);
diff --git a/fs/fcntl.c b/fs/fcntl.c
index 22764c7..0ffe61f 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -142,6 +142,7 @@
 	}
 	return ret;
 }
+EXPORT_SYMBOL(sys_dup);
 
 #define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | O_DIRECT | O_NOATIME)
 
diff --git a/fs/file.c b/fs/file.c
index 4c6992d..9770a25 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -268,6 +268,7 @@
 	/* All good, so we try */
 	return expand_fdtable(files, nr);
 }
+EXPORT_SYMBOL_GPL(expand_files);
 
 static int count_open_files(struct fdtable *fdt)
 {
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 5f3368a..64375fc 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -19,6 +19,9 @@
 #include <linux/pipe_fs_i.h>
 #include <linux/swap.h>
 #include <linux/splice.h>
+#ifdef CONFIG_MIPS
+#include <asm/cacheflush.h>
+#endif
 
 MODULE_ALIAS_MISCDEV(FUSE_MINOR);
 MODULE_ALIAS("devname:fuse");
@@ -655,6 +658,9 @@
 static int fuse_copy_do(struct fuse_copy_state *cs, void **val, unsigned *size)
 {
 	unsigned ncpy = min(*size, cs->len);
+#ifdef CONFIG_MIPS
+	__flush_cache_all();
+#endif
 	if (val) {
 		if (cs->write)
 			memcpy(cs->buf, *val, ncpy);
diff --git a/fs/jffs2/Kconfig b/fs/jffs2/Kconfig
index 6ae169c..90c8b77 100644
--- a/fs/jffs2/Kconfig
+++ b/fs/jffs2/Kconfig
@@ -139,6 +139,15 @@
 	  This feature was added in July, 2007. Say 'N' if you need
 	  compatibility with older bootloaders or kernels.
 
+config JFFS2_LZMA
+	bool "JFFS2 LZMA compression support" if JFFS2_COMPRESSION_OPTIONS
+	select LZMA_COMPRESS
+	select LZMA_DECOMPRESS
+	depends on JFFS2_FS
+	default n
+	help
+	  JFFS2 wrapper to the LZMA C SDK
+
 config JFFS2_RTIME
 	bool "JFFS2 RTIME compression support" if JFFS2_COMPRESSION_OPTIONS
 	depends on JFFS2_FS
diff --git a/fs/jffs2/Makefile b/fs/jffs2/Makefile
index 60e5d49..23ba6ef 100644
--- a/fs/jffs2/Makefile
+++ b/fs/jffs2/Makefile
@@ -18,4 +18,7 @@
 jffs2-$(CONFIG_JFFS2_RTIME)	+= compr_rtime.o
 jffs2-$(CONFIG_JFFS2_ZLIB)	+= compr_zlib.o
 jffs2-$(CONFIG_JFFS2_LZO)	+= compr_lzo.o
+jffs2-$(CONFIG_JFFS2_LZMA)      += compr_lzma.o
 jffs2-$(CONFIG_JFFS2_SUMMARY)   += summary.o
+
+CFLAGS_compr_lzma.o += -Iinclude/linux -Ilib/lzma
diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c
index 3005ec4..9572c26 100644
--- a/fs/jffs2/build.c
+++ b/fs/jffs2/build.c
@@ -112,6 +112,17 @@
 	dbg_fsbuild("scanned flash completely\n");
 	jffs2_dbg_dump_block_lists_nolock(c);
 
+	if (c->flags & (1 << 7)) {
+		printk("%s(): unlocking the mtd device... ", __func__);
+		if (c->mtd->unlock)
+			c->mtd->unlock(c->mtd, 0, c->mtd->size);
+		printk("done.\n");
+
+		printk("%s(): erasing all blocks after the end marker... ", __func__);
+		jffs2_erase_pending_blocks(c, -1);
+		printk("done.\n");
+	}
+
 	dbg_fsbuild("pass 1 starting\n");
 	c->flags |= JFFS2_SB_FLAG_BUILDING;
 	/* Now scan the directory tree, increasing nlink according to every dirent found. */
diff --git a/fs/jffs2/compr.c b/fs/jffs2/compr.c
index 5b6c9d1..0a947a8 100644
--- a/fs/jffs2/compr.c
+++ b/fs/jffs2/compr.c
@@ -374,6 +374,9 @@
 #ifdef CONFIG_JFFS2_LZO
 	jffs2_lzo_init();
 #endif
+#ifdef CONFIG_JFFS2_LZMA
+        jffs2_lzma_init();
+#endif
 /* Setting default compression mode */
 #ifdef CONFIG_JFFS2_CMODE_NONE
 	jffs2_compression_mode = JFFS2_COMPR_MODE_NONE;
@@ -397,6 +400,9 @@
 int jffs2_compressors_exit(void)
 {
 /* Unregistering compressors */
+#ifdef CONFIG_JFFS2_LZMA
+        jffs2_lzma_exit();
+#endif
 #ifdef CONFIG_JFFS2_LZO
 	jffs2_lzo_exit();
 #endif
diff --git a/fs/jffs2/compr.h b/fs/jffs2/compr.h
index 5e91d57..32db2e1 100644
--- a/fs/jffs2/compr.h
+++ b/fs/jffs2/compr.h
@@ -29,9 +29,9 @@
 #define JFFS2_DYNRUBIN_PRIORITY  20
 #define JFFS2_LZARI_PRIORITY     30
 #define JFFS2_RTIME_PRIORITY     50
-#define JFFS2_ZLIB_PRIORITY      60
-#define JFFS2_LZO_PRIORITY       80
-
+#define JFFS2_LZMA_PRIORITY      70
+#define JFFS2_ZLIB_PRIORITY      80
+#define JFFS2_LZO_PRIORITY       90
 
 #define JFFS2_RUBINMIPS_DISABLED /* RUBINs will be used only */
 #define JFFS2_DYNRUBIN_DISABLED  /*	   for decompression */
@@ -101,5 +101,9 @@
 int jffs2_lzo_init(void);
 void jffs2_lzo_exit(void);
 #endif
+#ifdef CONFIG_JFFS2_LZMA
+int jffs2_lzma_init(void);
+void jffs2_lzma_exit(void);
+#endif
 
 #endif /* __JFFS2_COMPR_H__ */
diff --git a/fs/jffs2/compr_lzma.c b/fs/jffs2/compr_lzma.c
new file mode 100644
index 0000000..0fe3b75
--- /dev/null
+++ b/fs/jffs2/compr_lzma.c
@@ -0,0 +1,128 @@
+/*
+ * JFFS2 -- Journalling Flash File System, Version 2.
+ *
+ * For licensing information, see the file 'LICENCE' in this directory.
+ *
+ * JFFS2 wrapper to the LZMA C SDK
+ *
+ */
+
+#include <linux/lzma.h>
+#include "compr.h"
+
+#ifdef __KERNEL__
+	static DEFINE_MUTEX(deflate_mutex);
+#endif
+
+CLzmaEncHandle *p;
+Byte propsEncoded[LZMA_PROPS_SIZE];
+SizeT propsSize = sizeof(propsEncoded);
+
+STATIC void lzma_free_workspace(void)
+{
+	LzmaEnc_Destroy(p, &lzma_alloc, &lzma_alloc);
+}
+
+STATIC int INIT lzma_alloc_workspace(CLzmaEncProps *props)
+{
+	if ((p = (CLzmaEncHandle *)LzmaEnc_Create(&lzma_alloc)) == NULL)
+	{
+		PRINT_ERROR("Failed to allocate lzma deflate workspace\n");
+		return -ENOMEM;
+	}
+
+	if (LzmaEnc_SetProps(p, props) != SZ_OK)
+	{
+		lzma_free_workspace();
+		return -1;
+	}
+	
+	if (LzmaEnc_WriteProperties(p, propsEncoded, &propsSize) != SZ_OK)
+	{
+		lzma_free_workspace();
+		return -1;
+	}
+
+        return 0;
+}
+
+STATIC int jffs2_lzma_compress(unsigned char *data_in, unsigned char *cpage_out,
+			      uint32_t *sourcelen, uint32_t *dstlen)
+{
+	SizeT compress_size = (SizeT)(*dstlen);
+	int ret;
+
+	#ifdef __KERNEL__
+		mutex_lock(&deflate_mutex);
+	#endif
+
+	ret = LzmaEnc_MemEncode(p, cpage_out, &compress_size, data_in, *sourcelen,
+		0, NULL, &lzma_alloc, &lzma_alloc);
+
+	#ifdef __KERNEL__
+		mutex_unlock(&deflate_mutex);
+	#endif
+
+	if (ret != SZ_OK)
+		return -1;
+
+	*dstlen = (uint32_t)compress_size;
+
+	return 0;
+}
+
+STATIC int jffs2_lzma_decompress(unsigned char *data_in, unsigned char *cpage_out,
+				 uint32_t srclen, uint32_t destlen)
+{
+	int ret;
+	SizeT dl = (SizeT)destlen;
+	SizeT sl = (SizeT)srclen;
+	ELzmaStatus status;
+	
+	ret = LzmaDecode(cpage_out, &dl, data_in, &sl, propsEncoded,
+		propsSize, LZMA_FINISH_ANY, &status, &lzma_alloc);
+
+	if (ret != SZ_OK || status == LZMA_STATUS_NOT_FINISHED || dl != (SizeT)destlen)
+		return -1;
+
+	return 0;
+}
+
+static struct jffs2_compressor jffs2_lzma_comp = {
+	.priority = JFFS2_LZMA_PRIORITY,
+	.name = "lzma",
+	.compr = JFFS2_COMPR_LZMA,
+	.compress = &jffs2_lzma_compress,
+	.decompress = &jffs2_lzma_decompress,
+	.disabled = 0,
+};
+
+int INIT jffs2_lzma_init(void)
+{
+        int ret;
+	CLzmaEncProps props;
+	LzmaEncProps_Init(&props);
+
+        props.dictSize = LZMA_BEST_DICT(0x2000);
+        props.level = LZMA_BEST_LEVEL;
+        props.lc = LZMA_BEST_LC;
+        props.lp = LZMA_BEST_LP;
+        props.pb = LZMA_BEST_PB;
+        props.fb = LZMA_BEST_FB;
+
+	ret = lzma_alloc_workspace(&props);
+        if (ret < 0)
+                return ret;
+
+	ret = jffs2_register_compressor(&jffs2_lzma_comp);
+	if (ret)
+		lzma_free_workspace();
+	
+        return ret;
+}
+
+void jffs2_lzma_exit(void)
+{
+	jffs2_unregister_compressor(&jffs2_lzma_comp);
+	lzma_free_workspace();
+}
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
index f994648..a0b74b2 100644
--- a/fs/jffs2/scan.c
+++ b/fs/jffs2/scan.c
@@ -72,7 +72,7 @@
 		return ret;
 	if ((ret = jffs2_scan_dirty_space(c, jeb, jeb->free_size)))
 		return ret;
-	/* Turned wasted size into dirty, since we apparently 
+	/* Turned wasted size into dirty, since we apparently
 	   think it's recoverable now. */
 	jeb->dirty_size += jeb->wasted_size;
 	c->dirty_size += jeb->wasted_size;
@@ -147,8 +147,11 @@
 		/* reset summary info for next eraseblock scan */
 		jffs2_sum_reset_collected(s);
 
-		ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset),
-						buf_size, s);
+		if (c->flags & (1 << 7))
+			ret = BLK_STATE_ALLFF;
+		else
+			ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset),
+							buf_size, s);
 
 		if (ret < 0)
 			goto out;
@@ -403,7 +406,7 @@
 	if (!ref)
 		return -ENOMEM;
 
-	/* BEFORE jffs2_build_xattr_subsystem() called, 
+	/* BEFORE jffs2_build_xattr_subsystem() called,
 	 * and AFTER xattr_ref is marked as a dead xref,
 	 * ref->xid is used to store 32bit xid, xd is not used
 	 * ref->ino is used to store 32bit inode-number, ic is not used
@@ -476,7 +479,7 @@
 		struct jffs2_sum_marker *sm;
 		void *sumptr = NULL;
 		uint32_t sumlen;
-	      
+
 		if (!buf_size) {
 			/* XIP case. Just look, point at the summary if it's there */
 			sm = (void *)buf + c->sector_size - sizeof(*sm);
@@ -492,9 +495,9 @@
 				buf_len = sizeof(*sm);
 
 			/* Read as much as we want into the _end_ of the preallocated buffer */
-			err = jffs2_fill_scan_buf(c, buf + buf_size - buf_len, 
+			err = jffs2_fill_scan_buf(c, buf + buf_size - buf_len,
 						  jeb->offset + c->sector_size - buf_len,
-						  buf_len);				
+						  buf_len);
 			if (err)
 				return err;
 
@@ -513,9 +516,9 @@
 				}
 				if (buf_len < sumlen) {
 					/* Need to read more so that the entire summary node is present */
-					err = jffs2_fill_scan_buf(c, sumptr, 
+					err = jffs2_fill_scan_buf(c, sumptr,
 								  jeb->offset + c->sector_size - sumlen,
-								  sumlen - buf_len);				
+								  sumlen - buf_len);
 					if (err)
 						return err;
 				}
@@ -528,7 +531,7 @@
 
 			if (buf_size && sumlen > buf_size)
 				kfree(sumptr);
-			/* If it returns with a real error, bail. 
+			/* If it returns with a real error, bail.
 			   If it returns positive, that's a block classification
 			   (i.e. BLK_STATE_xxx) so return that too.
 			   If it returns zero, fall through to full scan. */
@@ -549,6 +552,17 @@
 			return err;
 	}
 
+	if ((buf[0] == 0xde) &&
+		(buf[1] == 0xad) &&
+		(buf[2] == 0xc0) &&
+		(buf[3] == 0xde)) {
+		/* end of filesystem. erase everything after this point */
+		printk("%s(): End of filesystem marker found at 0x%x\n", __func__, jeb->offset);
+		c->flags |= (1 << 7);
+
+		return BLK_STATE_ALLFF;
+	}
+
 	/* We temporarily use 'ofs' as a pointer into the buffer/jeb */
 	ofs = 0;
 	max_ofs = EMPTY_SCAN_SIZE(c->sector_size);
@@ -674,7 +688,7 @@
 				scan_end = buf_len;
 				goto more_empty;
 			}
-			
+
 			/* See how much more there is to read in this eraseblock... */
 			buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);
 			if (!buf_len) {
@@ -910,7 +924,7 @@
 
 	D1(printk(KERN_DEBUG "Block at 0x%08x: free 0x%08x, dirty 0x%08x, unchecked 0x%08x, used 0x%08x, wasted 0x%08x\n",
 		  jeb->offset,jeb->free_size, jeb->dirty_size, jeb->unchecked_size, jeb->used_size, jeb->wasted_size));
-	
+
 	/* mark_node_obsolete can add to wasted !! */
 	if (jeb->wasted_size) {
 		jeb->dirty_size += jeb->wasted_size;
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
index f2d96b5..da3d5fc 100644
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -371,14 +371,41 @@
 	BUILD_BUG_ON(sizeof(struct jffs2_raw_inode) != 68);
 	BUILD_BUG_ON(sizeof(struct jffs2_raw_summary) != 32);
 
-	printk(KERN_INFO "JFFS2 version 2.2."
+	printk(KERN_INFO "JFFS2 version 2.2"
 #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
 	       " (NAND)"
 #endif
 #ifdef CONFIG_JFFS2_SUMMARY
-	       " (SUMMARY) "
+	       " (SUMMARY)"
 #endif
-	       " © 2001-2006 Red Hat, Inc.\n");
+#ifdef CONFIG_JFFS2_ZLIB
+	       " (ZLIB)"
+#endif
+#ifdef CONFIG_JFFS2_LZO
+	       " (LZO)"
+#endif
+#ifdef CONFIG_JFFS2_LZMA
+	       " (LZMA)"
+#endif
+#ifdef CONFIG_JFFS2_RTIME
+	       " (RTIME)"
+#endif
+#ifdef CONFIG_JFFS2_RUBIN
+	       " (RUBIN)"
+#endif
+#ifdef  CONFIG_JFFS2_CMODE_NONE
+	       " (CMODE_NONE)"
+#endif
+#ifdef CONFIG_JFFS2_CMODE_PRIORITY
+	       " (CMODE_PRIORITY)"
+#endif
+#ifdef CONFIG_JFFS2_CMODE_SIZE
+	       " (CMODE_SIZE)"
+#endif
+#ifdef CONFIG_JFFS2_CMODE_FAVOURLZO
+	       " (CMODE_FAVOURLZO)"
+#endif
+	       " (c) 2001-2006 Red Hat, Inc.\n");
 
 	jffs2_inode_cachep = kmem_cache_create("jffs2_i",
 					     sizeof(struct jffs2_inode_info),
diff --git a/fs/namespace.c b/fs/namespace.c
index e608199..2551ec0 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1325,6 +1325,24 @@
 	release_mounts(&umount_list);
 }
 
+struct vfsmount *clone_private_mount(struct path *path)
+{
+	struct mount *old_mnt = real_mount(path->mnt);
+	struct mount *new_mnt;
+
+	if (IS_MNT_UNBINDABLE(old_mnt))
+		return ERR_PTR(-EINVAL);
+
+	down_read(&namespace_sem);
+	new_mnt = clone_mnt(old_mnt, path->dentry, CL_PRIVATE);
+	up_read(&namespace_sem);
+	if (!new_mnt)
+		return ERR_PTR(-ENOMEM);
+
+	return &new_mnt->mnt;
+}
+EXPORT_SYMBOL_GPL(clone_private_mount);
+
 int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
 		   struct vfsmount *root)
 {
diff --git a/fs/open.c b/fs/open.c
index 77becc0..7f56fc1 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -644,24 +644,24 @@
 	return error;
 }
 
-static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
-					struct file *f,
-					int (*open)(struct inode *, struct file *),
-					const struct cred *cred)
+static struct file *__dentry_open(struct path *path, struct file *f,
+				  int (*open)(struct inode *, struct file *),
+				  const struct cred *cred)
 {
 	static const struct file_operations empty_fops = {};
 	struct inode *inode;
 	int error;
 
+	path_get(path);
 	f->f_mode = OPEN_FMODE(f->f_flags) | FMODE_LSEEK |
 				FMODE_PREAD | FMODE_PWRITE;
 
 	if (unlikely(f->f_flags & O_PATH))
 		f->f_mode = FMODE_PATH;
 
-	inode = dentry->d_inode;
+	inode = path->dentry->d_inode;
 	if (f->f_mode & FMODE_WRITE) {
-		error = __get_file_write_access(inode, mnt);
+		error = __get_file_write_access(inode, path->mnt);
 		if (error)
 			goto cleanup_file;
 		if (!special_file(inode->i_mode))
@@ -669,8 +669,7 @@
 	}
 
 	f->f_mapping = inode->i_mapping;
-	f->f_path.dentry = dentry;
-	f->f_path.mnt = mnt;
+	f->f_path = *path;
 	f->f_pos = 0;
 	file_sb_list_add(f, inode->i_sb);
 
@@ -727,7 +726,7 @@
 			 * here, so just reset the state.
 			 */
 			file_reset_write(f);
-			mnt_drop_write(mnt);
+			mnt_drop_write(path->mnt);
 		}
 	}
 	file_sb_list_del(f);
@@ -735,8 +734,7 @@
 	f->f_path.mnt = NULL;
 cleanup_file:
 	put_filp(f);
-	dput(dentry);
-	mntput(mnt);
+	path_put(path);
 	return ERR_PTR(error);
 }
 
@@ -762,14 +760,14 @@
 struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
 		int (*open)(struct inode *, struct file *))
 {
+	struct path path = { .dentry = dentry, .mnt = nd->path.mnt };
 	const struct cred *cred = current_cred();
 
 	if (IS_ERR(nd->intent.open.file))
 		goto out;
 	if (IS_ERR(dentry))
 		goto out_err;
-	nd->intent.open.file = __dentry_open(dget(dentry), mntget(nd->path.mnt),
-					     nd->intent.open.file,
+	nd->intent.open.file = __dentry_open(&path, nd->intent.open.file,
 					     open, cred);
 out:
 	return nd->intent.open.file;
@@ -797,11 +795,9 @@
 	nd->intent.open.file = NULL;
 
 	/* Has the filesystem initialised the file for us? */
-	if (filp->f_path.dentry == NULL) {
-		path_get(&nd->path);
-		filp = __dentry_open(nd->path.dentry, nd->path.mnt, filp,
-				     NULL, cred);
-	}
+	if (filp->f_path.dentry == NULL)
+		filp = vfs_open(&nd->path, filp, cred);
+
 	return filp;
 }
 
@@ -812,27 +808,48 @@
 struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags,
 			 const struct cred *cred)
 {
-	int error;
 	struct file *f;
+	struct file *ret;
+	struct path path = { .dentry = dentry, .mnt = mnt };
 
 	validate_creds(cred);
 
 	/* We must always pass in a valid mount pointer. */
 	BUG_ON(!mnt);
 
-	error = -ENFILE;
+	ret = ERR_PTR(-ENFILE);
 	f = get_empty_filp();
-	if (f == NULL) {
-		dput(dentry);
-		mntput(mnt);
-		return ERR_PTR(error);
+	if (f != NULL) {
+		f->f_flags = flags;
+		ret = vfs_open(&path, f, cred);
 	}
+	path_put(&path);
 
-	f->f_flags = flags;
-	return __dentry_open(dentry, mnt, f, NULL, cred);
+	return ret;
 }
 EXPORT_SYMBOL(dentry_open);
 
+/**
+ * vfs_open - open the file at the given path
+ * @path: path to open
+ * @filp: newly allocated file with f_flag initialized
+ * @cred: credentials to use
+ *
+ * Open the file.  If successful, the returned file will have acquired
+ * an additional reference for path.
+ */
+struct file *vfs_open(struct path *path, struct file *filp,
+		      const struct cred *cred)
+{
+	struct inode *inode = path->dentry->d_inode;
+
+	if (inode->i_op->open)
+		return inode->i_op->open(path->dentry, filp, cred);
+	else
+		return __dentry_open(path, filp, NULL, cred);
+}
+EXPORT_SYMBOL(vfs_open);
+
 static void __put_unused_fd(struct files_struct *files, unsigned int fd)
 {
 	struct fdtable *fdt = files_fdtable(files);
diff --git a/fs/overlayfs/Kconfig b/fs/overlayfs/Kconfig
new file mode 100644
index 0000000..c4517da
--- /dev/null
+++ b/fs/overlayfs/Kconfig
@@ -0,0 +1,4 @@
+config OVERLAYFS_FS
+	tristate "Overlay filesystem support"
+	help
+	  Add support for overlay filesystem.
diff --git a/fs/overlayfs/Makefile b/fs/overlayfs/Makefile
new file mode 100644
index 0000000..8f91889
--- /dev/null
+++ b/fs/overlayfs/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the overlay filesystem.
+#
+
+obj-$(CONFIG_OVERLAYFS_FS) += overlayfs.o
+
+overlayfs-objs := super.o inode.o dir.o readdir.o copy_up.o
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
new file mode 100644
index 0000000..398fa1c
--- /dev/null
+++ b/fs/overlayfs/copy_up.c
@@ -0,0 +1,384 @@
+/*
+ *
+ * Copyright (C) 2011 Novell 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/fs.h>
+#include <linux/slab.h>
+#include <linux/file.h>
+#include <linux/splice.h>
+#include <linux/xattr.h>
+#include <linux/security.h>
+#include <linux/uaccess.h>
+#include "overlayfs.h"
+
+#define OVL_COPY_UP_CHUNK_SIZE (1 << 20)
+
+static int ovl_copy_up_xattr(struct dentry *old, struct dentry *new)
+{
+	ssize_t list_size, size;
+	char *buf, *name, *value;
+	int error;
+
+	if (!old->d_inode->i_op->getxattr ||
+	    !new->d_inode->i_op->getxattr)
+		return 0;
+
+	list_size = vfs_listxattr(old, NULL, 0);
+	if (list_size <= 0) {
+		if (list_size == -EOPNOTSUPP)
+			return 0;
+		return list_size;
+	}
+
+	buf = kzalloc(list_size, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	error = -ENOMEM;
+	value = kmalloc(XATTR_SIZE_MAX, GFP_KERNEL);
+	if (!value)
+		goto out;
+
+	list_size = vfs_listxattr(old, buf, list_size);
+	if (list_size <= 0) {
+		error = list_size;
+		goto out_free_value;
+	}
+
+	for (name = buf; name < (buf + list_size); name += strlen(name) + 1) {
+		size = vfs_getxattr(old, name, value, XATTR_SIZE_MAX);
+		if (size <= 0) {
+			error = size;
+			goto out_free_value;
+		}
+		error = vfs_setxattr(new, name, value, size, 0);
+		if (error)
+			goto out_free_value;
+	}
+
+out_free_value:
+	kfree(value);
+out:
+	kfree(buf);
+	return error;
+}
+
+static int ovl_copy_up_data(struct path *old, struct path *new, loff_t len)
+{
+	struct file *old_file;
+	struct file *new_file;
+	int error = 0;
+
+	if (len == 0)
+		return 0;
+
+	old_file = ovl_path_open(old, O_RDONLY);
+	if (IS_ERR(old_file))
+		return PTR_ERR(old_file);
+
+	new_file = ovl_path_open(new, O_WRONLY);
+	if (IS_ERR(new_file)) {
+		error = PTR_ERR(new_file);
+		goto out_fput;
+	}
+
+	/* FIXME: copy up sparse files efficiently */
+	while (len) {
+		loff_t offset = new_file->f_pos;
+		size_t this_len = OVL_COPY_UP_CHUNK_SIZE;
+		long bytes;
+
+		if (len < this_len)
+			this_len = len;
+
+		if (signal_pending_state(TASK_KILLABLE, current)) {
+			error = -EINTR;
+			break;
+		}
+
+		bytes = do_splice_direct(old_file, &offset, new_file, this_len,
+				 SPLICE_F_MOVE);
+		if (bytes <= 0) {
+			error = bytes;
+			break;
+		}
+
+		len -= bytes;
+	}
+
+	fput(new_file);
+out_fput:
+	fput(old_file);
+	return error;
+}
+
+static char *ovl_read_symlink(struct dentry *realdentry)
+{
+	int res;
+	char *buf;
+	struct inode *inode = realdentry->d_inode;
+	mm_segment_t old_fs;
+
+	res = -EINVAL;
+	if (!inode->i_op->readlink)
+		goto err;
+
+	res = -ENOMEM;
+	buf = (char *) __get_free_page(GFP_KERNEL);
+	if (!buf)
+		goto err;
+
+	old_fs = get_fs();
+	set_fs(get_ds());
+	/* The cast to a user pointer is valid due to the set_fs() */
+	res = inode->i_op->readlink(realdentry,
+				    (char __user *)buf, PAGE_SIZE - 1);
+	set_fs(old_fs);
+	if (res < 0) {
+		free_page((unsigned long) buf);
+		goto err;
+	}
+	buf[res] = '\0';
+
+	return buf;
+
+err:
+	return ERR_PTR(res);
+}
+
+static int ovl_set_timestamps(struct dentry *upperdentry, struct kstat *stat)
+{
+	struct iattr attr = {
+		.ia_valid =
+		     ATTR_ATIME | ATTR_MTIME | ATTR_ATIME_SET | ATTR_MTIME_SET,
+		.ia_atime = stat->atime,
+		.ia_mtime = stat->mtime,
+	};
+
+	return notify_change(upperdentry, &attr);
+}
+
+static int ovl_set_mode(struct dentry *upperdentry, umode_t mode)
+{
+	struct iattr attr = {
+		.ia_valid = ATTR_MODE,
+		.ia_mode = mode,
+	};
+
+	return notify_change(upperdentry, &attr);
+}
+
+static int ovl_copy_up_locked(struct dentry *upperdir, struct dentry *dentry,
+			      struct path *lowerpath, struct kstat *stat,
+			      const char *link)
+{
+	int err;
+	struct path newpath;
+	umode_t mode = stat->mode;
+
+	/* Can't properly set mode on creation because of the umask */
+	stat->mode &= S_IFMT;
+
+	ovl_path_upper(dentry, &newpath);
+	WARN_ON(newpath.dentry);
+	newpath.dentry = ovl_upper_create(upperdir, dentry, stat, link);
+	if (IS_ERR(newpath.dentry))
+		return PTR_ERR(newpath.dentry);
+
+	if (S_ISREG(stat->mode)) {
+		err = ovl_copy_up_data(lowerpath, &newpath, stat->size);
+		if (err)
+			goto err_remove;
+	}
+
+	err = ovl_copy_up_xattr(lowerpath->dentry, newpath.dentry);
+	if (err)
+		goto err_remove;
+
+	mutex_lock(&newpath.dentry->d_inode->i_mutex);
+	if (!S_ISLNK(stat->mode))
+		err = ovl_set_mode(newpath.dentry, mode);
+	if (!err)
+		err = ovl_set_timestamps(newpath.dentry, stat);
+	mutex_unlock(&newpath.dentry->d_inode->i_mutex);
+	if (err)
+		goto err_remove;
+
+	ovl_dentry_update(dentry, newpath.dentry);
+
+	/*
+	 * Easiest way to get rid of the lower dentry reference is to
+	 * drop this dentry.  This is neither needed nor possible for
+	 * directories.
+	 */
+	if (!S_ISDIR(stat->mode))
+		d_drop(dentry);
+
+	return 0;
+
+err_remove:
+	if (S_ISDIR(stat->mode))
+		vfs_rmdir(upperdir->d_inode, newpath.dentry);
+	else
+		vfs_unlink(upperdir->d_inode, newpath.dentry);
+
+	dput(newpath.dentry);
+
+	return err;
+}
+
+/*
+ * Copy up a single dentry
+ *
+ * Directory renames only allowed on "pure upper" (already created on
+ * upper filesystem, never copied up).  Directories which are on lower or
+ * are merged may not be renamed.  For these -EXDEV is returned and
+ * userspace has to deal with it.  This means, when copying up a
+ * directory we can rely on it and ancestors being stable.
+ *
+ * Non-directory renames start with copy up of source if necessary.  The
+ * actual rename will only proceed once the copy up was successful.  Copy
+ * up uses upper parent i_mutex for exclusion.  Since rename can change
+ * d_parent it is possible that the copy up will lock the old parent.  At
+ * that point the file will have already been copied up anyway.
+ */
+static int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry,
+			   struct path *lowerpath, struct kstat *stat)
+{
+	int err;
+	struct kstat pstat;
+	struct path parentpath;
+	struct dentry *upperdir;
+	const struct cred *old_cred;
+	struct cred *override_cred;
+	char *link = NULL;
+
+	ovl_path_upper(parent, &parentpath);
+	upperdir = parentpath.dentry;
+
+	err = vfs_getattr(parentpath.mnt, parentpath.dentry, &pstat);
+	if (err)
+		return err;
+
+	if (S_ISLNK(stat->mode)) {
+		link = ovl_read_symlink(lowerpath->dentry);
+		if (IS_ERR(link))
+			return PTR_ERR(link);
+	}
+
+	err = -ENOMEM;
+	override_cred = prepare_creds();
+	if (!override_cred)
+		goto out_free_link;
+
+	override_cred->fsuid = stat->uid;
+	override_cred->fsgid = stat->gid;
+	/*
+	 * CAP_SYS_ADMIN for copying up extended attributes
+	 * CAP_DAC_OVERRIDE for create
+	 * CAP_FOWNER for chmod, timestamp update
+	 * CAP_FSETID for chmod
+	 * CAP_MKNOD for mknod
+	 */
+	cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN);
+	cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE);
+	cap_raise(override_cred->cap_effective, CAP_FOWNER);
+	cap_raise(override_cred->cap_effective, CAP_FSETID);
+	cap_raise(override_cred->cap_effective, CAP_MKNOD);
+	old_cred = override_creds(override_cred);
+
+	mutex_lock_nested(&upperdir->d_inode->i_mutex, I_MUTEX_PARENT);
+	if (ovl_path_type(dentry) != OVL_PATH_LOWER) {
+		err = 0;
+	} else {
+		err = ovl_copy_up_locked(upperdir, dentry, lowerpath,
+					 stat, link);
+		if (!err) {
+			/* Restore timestamps on parent (best effort) */
+			ovl_set_timestamps(upperdir, &pstat);
+		}
+	}
+
+	mutex_unlock(&upperdir->d_inode->i_mutex);
+
+	revert_creds(old_cred);
+	put_cred(override_cred);
+
+out_free_link:
+	if (link)
+		free_page((unsigned long) link);
+
+	return err;
+}
+
+int ovl_copy_up(struct dentry *dentry)
+{
+	int err;
+
+	err = 0;
+	while (!err) {
+		struct dentry *next;
+		struct dentry *parent;
+		struct path lowerpath;
+		struct kstat stat;
+		enum ovl_path_type type = ovl_path_type(dentry);
+
+		if (type != OVL_PATH_LOWER)
+			break;
+
+		next = dget(dentry);
+		/* find the topmost dentry not yet copied up */
+		for (;;) {
+			parent = dget_parent(next);
+
+			type = ovl_path_type(parent);
+			if (type != OVL_PATH_LOWER)
+				break;
+
+			dput(next);
+			next = parent;
+		}
+
+		ovl_path_lower(next, &lowerpath);
+		err = vfs_getattr(lowerpath.mnt, lowerpath.dentry, &stat);
+		if (!err)
+			err = ovl_copy_up_one(parent, next, &lowerpath, &stat);
+
+		dput(parent);
+		dput(next);
+	}
+
+	return err;
+}
+
+/* Optimize by not copying up the file first and truncating later */
+int ovl_copy_up_truncate(struct dentry *dentry, loff_t size)
+{
+	int err;
+	struct kstat stat;
+	struct path lowerpath;
+	struct dentry *parent = dget_parent(dentry);
+
+	err = ovl_copy_up(parent);
+	if (err)
+		goto out_dput_parent;
+
+	ovl_path_lower(dentry, &lowerpath);
+	err = vfs_getattr(lowerpath.mnt, lowerpath.dentry, &stat);
+	if (err)
+		goto out_dput_parent;
+
+	if (size < stat.size)
+		stat.size = size;
+
+	err = ovl_copy_up_one(parent, dentry, &lowerpath, &stat);
+
+out_dput_parent:
+	dput(parent);
+	return err;
+}
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
new file mode 100644
index 0000000..57bbb94
--- /dev/null
+++ b/fs/overlayfs/dir.c
@@ -0,0 +1,596 @@
+/*
+ *
+ * Copyright (C) 2011 Novell 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/fs.h>
+#include <linux/namei.h>
+#include <linux/xattr.h>
+#include <linux/security.h>
+#include "overlayfs.h"
+
+static const char *ovl_whiteout_symlink = "(overlay-whiteout)";
+
+static int ovl_whiteout(struct dentry *upperdir, struct dentry *dentry)
+{
+	int err;
+	struct dentry *newdentry;
+	const struct cred *old_cred;
+	struct cred *override_cred;
+
+	/* FIXME: recheck lower dentry to see if whiteout is really needed */
+
+	err = -ENOMEM;
+	override_cred = prepare_creds();
+	if (!override_cred)
+		goto out;
+
+	/*
+	 * CAP_SYS_ADMIN for setxattr
+	 * CAP_DAC_OVERRIDE for symlink creation
+	 * CAP_FOWNER for unlink in sticky directory
+	 */
+	cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN);
+	cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE);
+	cap_raise(override_cred->cap_effective, CAP_FOWNER);
+	override_cred->fsuid = 0;
+	override_cred->fsgid = 0;
+	old_cred = override_creds(override_cred);
+
+	newdentry = lookup_one_len(dentry->d_name.name, upperdir,
+				   dentry->d_name.len);
+	err = PTR_ERR(newdentry);
+	if (IS_ERR(newdentry))
+		goto out_put_cred;
+
+	/* Just been removed within the same locked region */
+	WARN_ON(newdentry->d_inode);
+
+	err = vfs_symlink(upperdir->d_inode, newdentry, ovl_whiteout_symlink);
+	if (err)
+		goto out_dput;
+
+	ovl_dentry_version_inc(dentry->d_parent);
+
+	err = vfs_setxattr(newdentry, ovl_whiteout_xattr, "y", 1, 0);
+	if (err)
+		vfs_unlink(upperdir->d_inode, newdentry);
+
+out_dput:
+	dput(newdentry);
+out_put_cred:
+	revert_creds(old_cred);
+	put_cred(override_cred);
+out:
+	if (err) {
+		/*
+		 * There's no way to recover from failure to whiteout.
+		 * What should we do?  Log a big fat error and... ?
+		 */
+		printk(KERN_ERR "overlayfs: ERROR - failed to whiteout '%s'\n",
+		       dentry->d_name.name);
+	}
+
+	return err;
+}
+
+static struct dentry *ovl_lookup_create(struct dentry *upperdir,
+					struct dentry *template)
+{
+	int err;
+	struct dentry *newdentry;
+	struct qstr *name = &template->d_name;
+
+	newdentry = lookup_one_len(name->name, upperdir, name->len);
+	if (IS_ERR(newdentry))
+		return newdentry;
+
+	if (newdentry->d_inode) {
+		const struct cred *old_cred;
+		struct cred *override_cred;
+
+		/* No need to check whiteout if lower parent is non-existent */
+		err = -EEXIST;
+		if (!ovl_dentry_lower(template->d_parent))
+			goto out_dput;
+
+		if (!S_ISLNK(newdentry->d_inode->i_mode))
+			goto out_dput;
+
+		err = -ENOMEM;
+		override_cred = prepare_creds();
+		if (!override_cred)
+			goto out_dput;
+
+		/*
+		 * CAP_SYS_ADMIN for getxattr
+		 * CAP_FOWNER for unlink in sticky directory
+		 */
+		cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN);
+		cap_raise(override_cred->cap_effective, CAP_FOWNER);
+		old_cred = override_creds(override_cred);
+
+		err = -EEXIST;
+		if (ovl_is_whiteout(newdentry))
+			err = vfs_unlink(upperdir->d_inode, newdentry);
+
+		revert_creds(old_cred);
+		put_cred(override_cred);
+		if (err)
+			goto out_dput;
+
+		dput(newdentry);
+		newdentry = lookup_one_len(name->name, upperdir, name->len);
+		if (IS_ERR(newdentry)) {
+			ovl_whiteout(upperdir, template);
+			return newdentry;
+		}
+
+		/*
+		 * Whiteout just been successfully removed, parent
+		 * i_mutex is still held, there's no way the lookup
+		 * could return positive.
+		 */
+		WARN_ON(newdentry->d_inode);
+	}
+
+	return newdentry;
+
+out_dput:
+	dput(newdentry);
+	return ERR_PTR(err);
+}
+
+struct dentry *ovl_upper_create(struct dentry *upperdir, struct dentry *dentry,
+				struct kstat *stat, const char *link)
+{
+	int err;
+	struct dentry *newdentry;
+	struct inode *dir = upperdir->d_inode;
+
+	newdentry = ovl_lookup_create(upperdir, dentry);
+	if (IS_ERR(newdentry))
+		goto out;
+
+	switch (stat->mode & S_IFMT) {
+	case S_IFREG:
+		err = vfs_create(dir, newdentry, stat->mode, NULL);
+		break;
+
+	case S_IFDIR:
+		err = vfs_mkdir(dir, newdentry, stat->mode);
+		break;
+
+	case S_IFCHR:
+	case S_IFBLK:
+	case S_IFIFO:
+	case S_IFSOCK:
+		err = vfs_mknod(dir, newdentry, stat->mode, stat->rdev);
+		break;
+
+	case S_IFLNK:
+		err = vfs_symlink(dir, newdentry, link);
+		break;
+
+	default:
+		err = -EPERM;
+	}
+	if (err) {
+		if (ovl_dentry_is_opaque(dentry))
+			ovl_whiteout(upperdir, dentry);
+		dput(newdentry);
+		newdentry = ERR_PTR(err);
+	} else if (WARN_ON(!newdentry->d_inode)) {
+		/*
+		 * Not quite sure if non-instantiated dentry is legal or not.
+		 * VFS doesn't seem to care so check and warn here.
+		 */
+		dput(newdentry);
+		newdentry = ERR_PTR(-ENOENT);
+	}
+
+out:
+	return newdentry;
+
+}
+
+static int ovl_set_opaque(struct dentry *upperdentry)
+{
+	int err;
+	const struct cred *old_cred;
+	struct cred *override_cred;
+
+	override_cred = prepare_creds();
+	if (!override_cred)
+		return -ENOMEM;
+
+	/* CAP_SYS_ADMIN for setxattr of "trusted" namespace */
+	cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN);
+	old_cred = override_creds(override_cred);
+	err = vfs_setxattr(upperdentry, ovl_opaque_xattr, "y", 1, 0);
+	revert_creds(old_cred);
+	put_cred(override_cred);
+
+	return err;
+}
+
+static int ovl_remove_opaque(struct dentry *upperdentry)
+{
+	int err;
+	const struct cred *old_cred;
+	struct cred *override_cred;
+
+	override_cred = prepare_creds();
+	if (!override_cred)
+		return -ENOMEM;
+
+	/* CAP_SYS_ADMIN for removexattr of "trusted" namespace */
+	cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN);
+	old_cred = override_creds(override_cred);
+	err = vfs_removexattr(upperdentry, ovl_opaque_xattr);
+	revert_creds(old_cred);
+	put_cred(override_cred);
+
+	return err;
+}
+
+static int ovl_dir_getattr(struct vfsmount *mnt, struct dentry *dentry,
+			 struct kstat *stat)
+{
+	int err;
+	enum ovl_path_type type;
+	struct path realpath;
+
+	type = ovl_path_real(dentry, &realpath);
+	err = vfs_getattr(realpath.mnt, realpath.dentry, stat);
+	if (err)
+		return err;
+
+	stat->dev = dentry->d_sb->s_dev;
+	stat->ino = dentry->d_inode->i_ino;
+
+	/*
+	 * It's probably not worth it to count subdirs to get the
+	 * correct link count.  nlink=1 seems to pacify 'find' and
+	 * other utilities.
+	 */
+	if (type == OVL_PATH_MERGE)
+		stat->nlink = 1;
+
+	return 0;
+}
+
+static int ovl_create_object(struct dentry *dentry, int mode, dev_t rdev,
+			     const char *link)
+{
+	int err;
+	struct dentry *newdentry;
+	struct dentry *upperdir;
+	struct inode *inode;
+	struct kstat stat = {
+		.mode = mode,
+		.rdev = rdev,
+	};
+
+	err = -ENOMEM;
+	inode = ovl_new_inode(dentry->d_sb, mode, dentry->d_fsdata);
+	if (!inode)
+		goto out;
+
+	err = ovl_copy_up(dentry->d_parent);
+	if (err)
+		goto out_iput;
+
+	upperdir = ovl_dentry_upper(dentry->d_parent);
+	mutex_lock_nested(&upperdir->d_inode->i_mutex, I_MUTEX_PARENT);
+
+	newdentry = ovl_upper_create(upperdir, dentry, &stat, link);
+	err = PTR_ERR(newdentry);
+	if (IS_ERR(newdentry))
+		goto out_unlock;
+
+	ovl_dentry_version_inc(dentry->d_parent);
+	if (ovl_dentry_is_opaque(dentry) && S_ISDIR(mode)) {
+		err = ovl_set_opaque(newdentry);
+		if (err) {
+			vfs_rmdir(upperdir->d_inode, newdentry);
+			ovl_whiteout(upperdir, dentry);
+			goto out_dput;
+		}
+	}
+	ovl_dentry_update(dentry, newdentry);
+	d_instantiate(dentry, inode);
+	inode = NULL;
+	newdentry = NULL;
+	err = 0;
+
+out_dput:
+	dput(newdentry);
+out_unlock:
+	mutex_unlock(&upperdir->d_inode->i_mutex);
+out_iput:
+	iput(inode);
+out:
+	return err;
+}
+
+static int ovl_create(struct inode *dir, struct dentry *dentry, umode_t mode,
+			struct nameidata *nd)
+{
+	return ovl_create_object(dentry, (mode & 07777) | S_IFREG, 0, NULL);
+}
+
+static int ovl_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
+{
+	return ovl_create_object(dentry, (mode & 07777) | S_IFDIR, 0, NULL);
+}
+
+static int ovl_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
+		     dev_t rdev)
+{
+	return ovl_create_object(dentry, mode, rdev, NULL);
+}
+
+static int ovl_symlink(struct inode *dir, struct dentry *dentry,
+			 const char *link)
+{
+	return ovl_create_object(dentry, S_IFLNK, 0, link);
+}
+
+static int ovl_do_remove(struct dentry *dentry, bool is_dir)
+{
+	int err;
+	enum ovl_path_type type;
+	struct path realpath;
+	struct dentry *upperdir;
+
+	err = ovl_copy_up(dentry->d_parent);
+	if (err)
+		return err;
+
+	upperdir = ovl_dentry_upper(dentry->d_parent);
+	mutex_lock_nested(&upperdir->d_inode->i_mutex, I_MUTEX_PARENT);
+	type = ovl_path_real(dentry, &realpath);
+	if (type != OVL_PATH_LOWER) {
+		err = -ESTALE;
+		if (realpath.dentry->d_parent != upperdir)
+			goto out_d_drop;
+
+		/* FIXME: create whiteout up front and rename to target */
+
+		if (is_dir)
+			err = vfs_rmdir(upperdir->d_inode, realpath.dentry);
+		else
+			err = vfs_unlink(upperdir->d_inode, realpath.dentry);
+		if (err)
+			goto out_d_drop;
+
+		ovl_dentry_version_inc(dentry->d_parent);
+	}
+
+	if (type != OVL_PATH_UPPER || ovl_dentry_is_opaque(dentry))
+		err = ovl_whiteout(upperdir, dentry);
+
+	/*
+	 * Keeping this dentry hashed would mean having to release
+	 * upperpath/lowerpath, which could only be done if we are the
+	 * sole user of this dentry.  Too tricky...  Just unhash for
+	 * now.
+	 */
+out_d_drop:
+	d_drop(dentry);
+	mutex_unlock(&upperdir->d_inode->i_mutex);
+
+	return err;
+}
+
+static int ovl_unlink(struct inode *dir, struct dentry *dentry)
+{
+	return ovl_do_remove(dentry, false);
+}
+
+
+static int ovl_rmdir(struct inode *dir, struct dentry *dentry)
+{
+	int err;
+	enum ovl_path_type type;
+
+	type = ovl_path_type(dentry);
+	if (type != OVL_PATH_UPPER) {
+		err = ovl_check_empty_and_clear(dentry, type);
+		if (err)
+			return err;
+	}
+
+	return ovl_do_remove(dentry, true);
+}
+
+static int ovl_link(struct dentry *old, struct inode *newdir,
+		    struct dentry *new)
+{
+	int err;
+	struct dentry *olddentry;
+	struct dentry *newdentry;
+	struct dentry *upperdir;
+
+	err = ovl_copy_up(old);
+	if (err)
+		goto out;
+
+	err = ovl_copy_up(new->d_parent);
+	if (err)
+		goto out;
+
+	upperdir = ovl_dentry_upper(new->d_parent);
+	mutex_lock_nested(&upperdir->d_inode->i_mutex, I_MUTEX_PARENT);
+	newdentry = ovl_lookup_create(upperdir, new);
+	err = PTR_ERR(newdentry);
+	if (IS_ERR(newdentry))
+		goto out_unlock;
+
+	olddentry = ovl_dentry_upper(old);
+	err = vfs_link(olddentry, upperdir->d_inode, newdentry);
+	if (!err) {
+		if (WARN_ON(!newdentry->d_inode)) {
+			dput(newdentry);
+			err = -ENOENT;
+			goto out_unlock;
+		}
+
+		ovl_dentry_version_inc(new->d_parent);
+		ovl_dentry_update(new, newdentry);
+
+		ihold(old->d_inode);
+		d_instantiate(new, old->d_inode);
+	} else {
+		if (ovl_dentry_is_opaque(new))
+			ovl_whiteout(upperdir, new);
+		dput(newdentry);
+	}
+out_unlock:
+	mutex_unlock(&upperdir->d_inode->i_mutex);
+out:
+	return err;
+
+}
+
+static int ovl_rename(struct inode *olddir, struct dentry *old,
+			struct inode *newdir, struct dentry *new)
+{
+	int err;
+	enum ovl_path_type old_type;
+	enum ovl_path_type new_type;
+	struct dentry *old_upperdir;
+	struct dentry *new_upperdir;
+	struct dentry *olddentry;
+	struct dentry *newdentry;
+	struct dentry *trap;
+	bool old_opaque;
+	bool new_opaque;
+	bool new_create = false;
+	bool is_dir = S_ISDIR(old->d_inode->i_mode);
+
+	/* Don't copy up directory trees */
+	old_type = ovl_path_type(old);
+	if (old_type != OVL_PATH_UPPER && is_dir)
+		return -EXDEV;
+
+	if (new->d_inode) {
+		new_type = ovl_path_type(new);
+
+		if (new_type == OVL_PATH_LOWER && old_type == OVL_PATH_LOWER) {
+			if (ovl_dentry_lower(old)->d_inode ==
+			    ovl_dentry_lower(new)->d_inode)
+				return 0;
+		}
+		if (new_type != OVL_PATH_LOWER && old_type != OVL_PATH_LOWER) {
+			if (ovl_dentry_upper(old)->d_inode ==
+			    ovl_dentry_upper(new)->d_inode)
+				return 0;
+		}
+
+		if (new_type != OVL_PATH_UPPER &&
+		    S_ISDIR(new->d_inode->i_mode)) {
+			err = ovl_check_empty_and_clear(new, new_type);
+			if (err)
+				return err;
+		}
+	} else {
+		new_type = OVL_PATH_UPPER;
+	}
+
+	err = ovl_copy_up(old);
+	if (err)
+		return err;
+
+	err = ovl_copy_up(new->d_parent);
+	if (err)
+		return err;
+
+	old_upperdir = ovl_dentry_upper(old->d_parent);
+	new_upperdir = ovl_dentry_upper(new->d_parent);
+
+	trap = lock_rename(new_upperdir, old_upperdir);
+
+	olddentry = ovl_dentry_upper(old);
+	newdentry = ovl_dentry_upper(new);
+	if (newdentry) {
+		dget(newdentry);
+	} else {
+		new_create = true;
+		newdentry = ovl_lookup_create(new_upperdir, new);
+		err = PTR_ERR(newdentry);
+		if (IS_ERR(newdentry))
+			goto out_unlock;
+	}
+
+	err = -ESTALE;
+	if (olddentry->d_parent != old_upperdir)
+		goto out_dput;
+	if (newdentry->d_parent != new_upperdir)
+		goto out_dput;
+	if (olddentry == trap)
+		goto out_dput;
+	if (newdentry == trap)
+		goto out_dput;
+
+	old_opaque = ovl_dentry_is_opaque(old);
+	new_opaque = ovl_dentry_is_opaque(new) || new_type != OVL_PATH_UPPER;
+
+	if (is_dir && !old_opaque && new_opaque) {
+		err = ovl_set_opaque(olddentry);
+		if (err)
+			goto out_dput;
+	}
+
+	err = vfs_rename(old_upperdir->d_inode, olddentry,
+			 new_upperdir->d_inode, newdentry);
+
+	if (err) {
+		if (new_create && ovl_dentry_is_opaque(new))
+			ovl_whiteout(new_upperdir, new);
+		if (is_dir && !old_opaque && new_opaque)
+			ovl_remove_opaque(olddentry);
+		goto out_dput;
+	}
+
+	if (old_type != OVL_PATH_UPPER || old_opaque)
+		err = ovl_whiteout(old_upperdir, old);
+	if (is_dir && old_opaque && !new_opaque)
+		ovl_remove_opaque(olddentry);
+
+	if (old_opaque != new_opaque)
+		ovl_dentry_set_opaque(old, new_opaque);
+
+	ovl_dentry_version_inc(old->d_parent);
+	ovl_dentry_version_inc(new->d_parent);
+
+out_dput:
+	dput(newdentry);
+out_unlock:
+	unlock_rename(new_upperdir, old_upperdir);
+	return err;
+}
+
+const struct inode_operations ovl_dir_inode_operations = {
+	.lookup		= ovl_lookup,
+	.mkdir		= ovl_mkdir,
+	.symlink	= ovl_symlink,
+	.unlink		= ovl_unlink,
+	.rmdir		= ovl_rmdir,
+	.rename		= ovl_rename,
+	.link		= ovl_link,
+	.setattr	= ovl_setattr,
+	.create		= ovl_create,
+	.mknod		= ovl_mknod,
+	.permission	= ovl_permission,
+	.getattr	= ovl_dir_getattr,
+	.setxattr	= ovl_setxattr,
+	.getxattr	= ovl_getxattr,
+	.listxattr	= ovl_listxattr,
+	.removexattr	= ovl_removexattr,
+};
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
new file mode 100644
index 0000000..ba1a777
--- /dev/null
+++ b/fs/overlayfs/inode.c
@@ -0,0 +1,384 @@
+/*
+ *
+ * Copyright (C) 2011 Novell 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/fs.h>
+#include <linux/slab.h>
+#include <linux/xattr.h>
+#include "overlayfs.h"
+
+int ovl_setattr(struct dentry *dentry, struct iattr *attr)
+{
+	struct dentry *upperdentry;
+	int err;
+
+	if ((attr->ia_valid & ATTR_SIZE) && !ovl_dentry_upper(dentry))
+		err = ovl_copy_up_truncate(dentry, attr->ia_size);
+	else
+		err = ovl_copy_up(dentry);
+	if (err)
+		return err;
+
+	upperdentry = ovl_dentry_upper(dentry);
+
+	if (attr->ia_valid & (ATTR_KILL_SUID|ATTR_KILL_SGID))
+		attr->ia_valid &= ~ATTR_MODE;
+
+	mutex_lock(&upperdentry->d_inode->i_mutex);
+	err = notify_change(upperdentry, attr);
+	mutex_unlock(&upperdentry->d_inode->i_mutex);
+
+	return err;
+}
+
+static int ovl_getattr(struct vfsmount *mnt, struct dentry *dentry,
+			 struct kstat *stat)
+{
+	struct path realpath;
+
+	ovl_path_real(dentry, &realpath);
+	return vfs_getattr(realpath.mnt, realpath.dentry, stat);
+}
+
+int ovl_permission(struct inode *inode, int mask)
+{
+	struct ovl_entry *oe;
+	struct dentry *alias = NULL;
+	struct inode *realinode;
+	struct dentry *realdentry;
+	bool is_upper;
+	int err;
+
+	if (S_ISDIR(inode->i_mode)) {
+		oe = inode->i_private;
+	} else if (mask & MAY_NOT_BLOCK) {
+		return -ECHILD;
+	} else {
+		/*
+		 * For non-directories find an alias and get the info
+		 * from there.
+		 */
+		spin_lock(&inode->i_lock);
+		if (WARN_ON(list_empty(&inode->i_dentry))) {
+			spin_unlock(&inode->i_lock);
+			return -ENOENT;
+		}
+		alias = list_entry(inode->i_dentry.next,
+				   struct dentry, d_alias);
+		dget(alias);
+		spin_unlock(&inode->i_lock);
+		oe = alias->d_fsdata;
+	}
+
+	realdentry = ovl_entry_real(oe, &is_upper);
+
+	/* Careful in RCU walk mode */
+	realinode = ACCESS_ONCE(realdentry->d_inode);
+	if (!realinode) {
+		WARN_ON(!(mask & MAY_NOT_BLOCK));
+		err = -ENOENT;
+		goto out_dput;
+	}
+
+	if (mask & MAY_WRITE) {
+		umode_t mode = realinode->i_mode;
+
+		/*
+		 * Writes will always be redirected to upper layer, so
+		 * ignore lower layer being read-only.
+		 *
+		 * If the overlay itself is read-only then proceed
+		 * with the permission check, don't return EROFS.
+		 * This will only happen if this is the lower layer of
+		 * another overlayfs.
+		 *
+		 * If upper fs becomes read-only after the overlay was
+		 * constructed return EROFS to prevent modification of
+		 * upper layer.
+		 */
+		err = -EROFS;
+		if (is_upper && !IS_RDONLY(inode) && IS_RDONLY(realinode) &&
+		    (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
+			goto out_dput;
+
+		/*
+		 * Nobody gets write access to an immutable file.
+		 */
+		err = -EACCES;
+		if (IS_IMMUTABLE(realinode))
+			goto out_dput;
+	}
+
+	if (realinode->i_op->permission)
+		err = realinode->i_op->permission(realinode, mask);
+	else
+		err = generic_permission(realinode, mask);
+out_dput:
+	dput(alias);
+	return err;
+}
+
+
+struct ovl_link_data {
+	struct dentry *realdentry;
+	void *cookie;
+};
+
+static void *ovl_follow_link(struct dentry *dentry, struct nameidata *nd)
+{
+	void *ret;
+	struct dentry *realdentry;
+	struct inode *realinode;
+
+	realdentry = ovl_dentry_real(dentry);
+	realinode = realdentry->d_inode;
+
+	if (WARN_ON(!realinode->i_op->follow_link))
+		return ERR_PTR(-EPERM);
+
+	ret = realinode->i_op->follow_link(realdentry, nd);
+	if (IS_ERR(ret))
+		return ret;
+
+	if (realinode->i_op->put_link) {
+		struct ovl_link_data *data;
+
+		data = kmalloc(sizeof(struct ovl_link_data), GFP_KERNEL);
+		if (!data) {
+			realinode->i_op->put_link(realdentry, nd, ret);
+			return ERR_PTR(-ENOMEM);
+		}
+		data->realdentry = realdentry;
+		data->cookie = ret;
+
+		return data;
+	} else {
+		return NULL;
+	}
+}
+
+static void ovl_put_link(struct dentry *dentry, struct nameidata *nd, void *c)
+{
+	struct inode *realinode;
+	struct ovl_link_data *data = c;
+
+	if (!data)
+		return;
+
+	realinode = data->realdentry->d_inode;
+	realinode->i_op->put_link(data->realdentry, nd, data->cookie);
+	kfree(data);
+}
+
+static int ovl_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
+{
+	struct path realpath;
+	struct inode *realinode;
+
+	ovl_path_real(dentry, &realpath);
+	realinode = realpath.dentry->d_inode;
+
+	if (!realinode->i_op->readlink)
+		return -EINVAL;
+
+	touch_atime(realpath.mnt, realpath.dentry);
+
+	return realinode->i_op->readlink(realpath.dentry, buf, bufsiz);
+}
+
+
+static bool ovl_is_private_xattr(const char *name)
+{
+	return strncmp(name, "trusted.overlay.", 14) == 0;
+}
+
+int ovl_setxattr(struct dentry *dentry, const char *name,
+		 const void *value, size_t size, int flags)
+{
+	int err;
+	struct dentry *upperdentry;
+
+	if (ovl_is_private_xattr(name))
+		return -EPERM;
+
+	err = ovl_copy_up(dentry);
+	if (err)
+		return err;
+
+	upperdentry = ovl_dentry_upper(dentry);
+	return  vfs_setxattr(upperdentry, name, value, size, flags);
+}
+
+ssize_t ovl_getxattr(struct dentry *dentry, const char *name,
+		     void *value, size_t size)
+{
+	if (ovl_path_type(dentry->d_parent) == OVL_PATH_MERGE &&
+	    ovl_is_private_xattr(name))
+		return -ENODATA;
+
+	return vfs_getxattr(ovl_dentry_real(dentry), name, value, size);
+}
+
+ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size)
+{
+	ssize_t res;
+	int off;
+
+	res = vfs_listxattr(ovl_dentry_real(dentry), list, size);
+	if (res <= 0 || size == 0)
+		return res;
+
+	if (ovl_path_type(dentry->d_parent) != OVL_PATH_MERGE)
+		return res;
+
+	/* filter out private xattrs */
+	for (off = 0; off < res;) {
+		char *s = list + off;
+		size_t slen = strlen(s) + 1;
+
+		BUG_ON(off + slen > res);
+
+		if (ovl_is_private_xattr(s)) {
+			res -= slen;
+			memmove(s, s + slen, res - off);
+		} else {
+			off += slen;
+		}
+	}
+
+	return res;
+}
+
+int ovl_removexattr(struct dentry *dentry, const char *name)
+{
+	int err;
+	struct path realpath;
+	enum ovl_path_type type;
+
+	if (ovl_path_type(dentry->d_parent) == OVL_PATH_MERGE &&
+	    ovl_is_private_xattr(name))
+		return -ENODATA;
+
+	type = ovl_path_real(dentry, &realpath);
+	if (type == OVL_PATH_LOWER) {
+		err = vfs_getxattr(realpath.dentry, name, NULL, 0);
+		if (err < 0)
+			return err;
+
+		err = ovl_copy_up(dentry);
+		if (err)
+			return err;
+
+		ovl_path_upper(dentry, &realpath);
+	}
+
+	return vfs_removexattr(realpath.dentry, name);
+}
+
+static bool ovl_open_need_copy_up(int flags, enum ovl_path_type type,
+				  struct dentry *realdentry)
+{
+	if (type != OVL_PATH_LOWER)
+		return false;
+
+	if (special_file(realdentry->d_inode->i_mode))
+		return false;
+
+	if (!(OPEN_FMODE(flags) & FMODE_WRITE) && !(flags & O_TRUNC))
+		return false;
+
+	return true;
+}
+
+static struct file *ovl_open(struct dentry *dentry, struct file *file,
+			     const struct cred *cred)
+{
+	int err;
+	struct path realpath;
+	enum ovl_path_type type;
+
+	type = ovl_path_real(dentry, &realpath);
+	if (ovl_open_need_copy_up(file->f_flags, type, realpath.dentry)) {
+		if (file->f_flags & O_TRUNC)
+			err = ovl_copy_up_truncate(dentry, 0);
+		else
+			err = ovl_copy_up(dentry);
+		if (err)
+			return ERR_PTR(err);
+
+		ovl_path_upper(dentry, &realpath);
+	}
+
+	return vfs_open(&realpath, file, cred);
+}
+
+static const struct inode_operations ovl_file_inode_operations = {
+	.setattr	= ovl_setattr,
+	.permission	= ovl_permission,
+	.getattr	= ovl_getattr,
+	.setxattr	= ovl_setxattr,
+	.getxattr	= ovl_getxattr,
+	.listxattr	= ovl_listxattr,
+	.removexattr	= ovl_removexattr,
+	.open		= ovl_open,
+};
+
+static const struct inode_operations ovl_symlink_inode_operations = {
+	.setattr	= ovl_setattr,
+	.follow_link	= ovl_follow_link,
+	.put_link	= ovl_put_link,
+	.readlink	= ovl_readlink,
+	.getattr	= ovl_getattr,
+	.setxattr	= ovl_setxattr,
+	.getxattr	= ovl_getxattr,
+	.listxattr	= ovl_listxattr,
+	.removexattr	= ovl_removexattr,
+};
+
+struct inode *ovl_new_inode(struct super_block *sb, umode_t mode,
+			    struct ovl_entry *oe)
+{
+	struct inode *inode;
+
+	inode = new_inode(sb);
+	if (!inode)
+		return NULL;
+
+	mode &= S_IFMT;
+
+	inode->i_ino = get_next_ino();
+	inode->i_mode = mode;
+	inode->i_flags |= S_NOATIME | S_NOCMTIME;
+
+	switch (mode) {
+	case S_IFDIR:
+		inode->i_private = oe;
+		inode->i_op = &ovl_dir_inode_operations;
+		inode->i_fop = &ovl_dir_operations;
+		break;
+
+	case S_IFLNK:
+		inode->i_op = &ovl_symlink_inode_operations;
+		break;
+
+	case S_IFREG:
+	case S_IFSOCK:
+	case S_IFBLK:
+	case S_IFCHR:
+	case S_IFIFO:
+		inode->i_op = &ovl_file_inode_operations;
+		break;
+
+	default:
+		WARN(1, "illegal file type: %i\n", mode);
+		inode = NULL;
+	}
+
+	return inode;
+
+}
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
new file mode 100644
index 0000000..1dd05f7
--- /dev/null
+++ b/fs/overlayfs/overlayfs.h
@@ -0,0 +1,64 @@
+/*
+ *
+ * Copyright (C) 2011 Novell 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.
+ */
+
+struct ovl_entry;
+
+enum ovl_path_type {
+	OVL_PATH_UPPER,
+	OVL_PATH_MERGE,
+	OVL_PATH_LOWER,
+};
+
+extern const char *ovl_opaque_xattr;
+extern const char *ovl_whiteout_xattr;
+extern const struct dentry_operations ovl_dentry_operations;
+
+enum ovl_path_type ovl_path_type(struct dentry *dentry);
+u64 ovl_dentry_version_get(struct dentry *dentry);
+void ovl_dentry_version_inc(struct dentry *dentry);
+void ovl_path_upper(struct dentry *dentry, struct path *path);
+void ovl_path_lower(struct dentry *dentry, struct path *path);
+enum ovl_path_type ovl_path_real(struct dentry *dentry, struct path *path);
+struct dentry *ovl_dentry_upper(struct dentry *dentry);
+struct dentry *ovl_dentry_lower(struct dentry *dentry);
+struct dentry *ovl_dentry_real(struct dentry *dentry);
+struct dentry *ovl_entry_real(struct ovl_entry *oe, bool *is_upper);
+bool ovl_dentry_is_opaque(struct dentry *dentry);
+void ovl_dentry_set_opaque(struct dentry *dentry, bool opaque);
+bool ovl_is_whiteout(struct dentry *dentry);
+void ovl_dentry_update(struct dentry *dentry, struct dentry *upperdentry);
+struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
+			  struct nameidata *nd);
+struct file *ovl_path_open(struct path *path, int flags);
+
+struct dentry *ovl_upper_create(struct dentry *upperdir, struct dentry *dentry,
+				struct kstat *stat, const char *link);
+
+/* readdir.c */
+extern const struct file_operations ovl_dir_operations;
+int ovl_check_empty_and_clear(struct dentry *dentry, enum ovl_path_type type);
+
+/* inode.c */
+int ovl_setattr(struct dentry *dentry, struct iattr *attr);
+int ovl_permission(struct inode *inode, int mask);
+int ovl_setxattr(struct dentry *dentry, const char *name,
+		 const void *value, size_t size, int flags);
+ssize_t ovl_getxattr(struct dentry *dentry, const char *name,
+		     void *value, size_t size);
+ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size);
+int ovl_removexattr(struct dentry *dentry, const char *name);
+
+struct inode *ovl_new_inode(struct super_block *sb, umode_t mode,
+			    struct ovl_entry *oe);
+/* dir.c */
+extern const struct inode_operations ovl_dir_inode_operations;
+
+/* copy_up.c */
+int ovl_copy_up(struct dentry *dentry);
+int ovl_copy_up_truncate(struct dentry *dentry, loff_t size);
diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c
new file mode 100644
index 0000000..ed8fbad
--- /dev/null
+++ b/fs/overlayfs/readdir.c
@@ -0,0 +1,565 @@
+/*
+ *
+ * Copyright (C) 2011 Novell 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/fs.h>
+#include <linux/slab.h>
+#include <linux/namei.h>
+#include <linux/file.h>
+#include <linux/xattr.h>
+#include <linux/rbtree.h>
+#include <linux/security.h>
+#include "overlayfs.h"
+
+struct ovl_cache_entry {
+	const char *name;
+	unsigned int len;
+	unsigned int type;
+	u64 ino;
+	bool is_whiteout;
+	struct list_head l_node;
+	struct rb_node node;
+};
+
+struct ovl_readdir_data {
+	struct rb_root *root;
+	struct list_head *list;
+	struct list_head *middle;
+	struct dentry *dir;
+	int count;
+	int err;
+};
+
+struct ovl_dir_file {
+	bool is_real;
+	bool is_cached;
+	struct list_head cursor;
+	u64 cache_version;
+	struct list_head cache;
+	struct file *realfile;
+};
+
+static struct ovl_cache_entry *ovl_cache_entry_from_node(struct rb_node *n)
+{
+	return container_of(n, struct ovl_cache_entry, node);
+}
+
+static struct ovl_cache_entry *ovl_cache_entry_find(struct rb_root *root,
+						    const char *name, int len)
+{
+	struct rb_node *node = root->rb_node;
+	int cmp;
+
+	while (node) {
+		struct ovl_cache_entry *p = ovl_cache_entry_from_node(node);
+
+		cmp = strncmp(name, p->name, len);
+		if (cmp > 0)
+			node = p->node.rb_right;
+		else if (cmp < 0 || len < p->len)
+			node = p->node.rb_left;
+		else
+			return p;
+	}
+
+	return NULL;
+}
+
+static struct ovl_cache_entry *ovl_cache_entry_new(const char *name, int len,
+						   u64 ino, unsigned int d_type)
+{
+	struct ovl_cache_entry *p;
+
+	p = kmalloc(sizeof(*p) + len + 1, GFP_KERNEL);
+	if (p) {
+		char *name_copy = (char *) (p + 1);
+		memcpy(name_copy, name, len);
+		name_copy[len] = '\0';
+		p->name = name_copy;
+		p->len = len;
+		p->type = d_type;
+		p->ino = ino;
+		p->is_whiteout = false;
+	}
+
+	return p;
+}
+
+static int ovl_cache_entry_add_rb(struct ovl_readdir_data *rdd,
+				  const char *name, int len, u64 ino,
+				  unsigned int d_type)
+{
+	struct rb_node **newp = &rdd->root->rb_node;
+	struct rb_node *parent = NULL;
+	struct ovl_cache_entry *p;
+
+	while (*newp) {
+		int cmp;
+		struct ovl_cache_entry *tmp;
+
+		parent = *newp;
+		tmp = ovl_cache_entry_from_node(*newp);
+		cmp = strncmp(name, tmp->name, len);
+		if (cmp > 0)
+			newp = &tmp->node.rb_right;
+		else if (cmp < 0 || len < tmp->len)
+			newp = &tmp->node.rb_left;
+		else
+			return 0;
+	}
+
+	p = ovl_cache_entry_new(name, len, ino, d_type);
+	if (p == NULL)
+		return -ENOMEM;
+
+	list_add_tail(&p->l_node, rdd->list);
+	rb_link_node(&p->node, parent, newp);
+	rb_insert_color(&p->node, rdd->root);
+
+	return 0;
+}
+
+static int ovl_fill_lower(void *buf, const char *name, int namelen,
+			    loff_t offset, u64 ino, unsigned int d_type)
+{
+	struct ovl_readdir_data *rdd = buf;
+	struct ovl_cache_entry *p;
+
+	rdd->count++;
+	p = ovl_cache_entry_find(rdd->root, name, namelen);
+	if (p) {
+		list_move_tail(&p->l_node, rdd->middle);
+	} else {
+		p = ovl_cache_entry_new(name, namelen, ino, d_type);
+		if (p == NULL)
+			rdd->err = -ENOMEM;
+		else
+			list_add_tail(&p->l_node, rdd->middle);
+	}
+
+	return rdd->err;
+}
+
+static void ovl_cache_free(struct list_head *list)
+{
+	struct ovl_cache_entry *p;
+	struct ovl_cache_entry *n;
+
+	list_for_each_entry_safe(p, n, list, l_node)
+		kfree(p);
+
+	INIT_LIST_HEAD(list);
+}
+
+static int ovl_fill_upper(void *buf, const char *name, int namelen,
+			  loff_t offset, u64 ino, unsigned int d_type)
+{
+	struct ovl_readdir_data *rdd = buf;
+
+	rdd->count++;
+	return ovl_cache_entry_add_rb(rdd, name, namelen, ino, d_type);
+}
+
+static inline int ovl_dir_read(struct path *realpath,
+			       struct ovl_readdir_data *rdd, filldir_t filler)
+{
+	struct file *realfile;
+	int err;
+
+	realfile = ovl_path_open(realpath, O_RDONLY | O_DIRECTORY);
+	if (IS_ERR(realfile))
+		return PTR_ERR(realfile);
+
+	do {
+		rdd->count = 0;
+		rdd->err = 0;
+		err = vfs_readdir(realfile, filler, rdd);
+		if (err >= 0)
+			err = rdd->err;
+	} while (!err && rdd->count);
+	fput(realfile);
+
+	return 0;
+}
+
+static void ovl_dir_reset(struct file *file)
+{
+	struct ovl_dir_file *od = file->private_data;
+	enum ovl_path_type type = ovl_path_type(file->f_path.dentry);
+
+	if (ovl_dentry_version_get(file->f_path.dentry) != od->cache_version) {
+		list_del_init(&od->cursor);
+		ovl_cache_free(&od->cache);
+		od->is_cached = false;
+	}
+	WARN_ON(!od->is_real && type != OVL_PATH_MERGE);
+	if (od->is_real && type == OVL_PATH_MERGE) {
+		fput(od->realfile);
+		od->realfile = NULL;
+		od->is_real = false;
+	}
+}
+
+static int ovl_dir_mark_whiteouts(struct ovl_readdir_data *rdd)
+{
+	struct ovl_cache_entry *p;
+	struct dentry *dentry;
+	const struct cred *old_cred;
+	struct cred *override_cred;
+
+	override_cred = prepare_creds();
+	if (!override_cred) {
+		ovl_cache_free(rdd->list);
+		return -ENOMEM;
+	}
+
+	/*
+	 * CAP_SYS_ADMIN for getxattr
+	 * CAP_DAC_OVERRIDE for lookup
+	 */
+	cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN);
+	cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE);
+	old_cred = override_creds(override_cred);
+
+	mutex_lock(&rdd->dir->d_inode->i_mutex);
+	list_for_each_entry(p, rdd->list, l_node) {
+		if (p->type != DT_LNK)
+			continue;
+
+		dentry = lookup_one_len(p->name, rdd->dir, p->len);
+		if (IS_ERR(dentry))
+			continue;
+
+		p->is_whiteout = ovl_is_whiteout(dentry);
+		dput(dentry);
+	}
+	mutex_unlock(&rdd->dir->d_inode->i_mutex);
+
+	revert_creds(old_cred);
+	put_cred(override_cred);
+
+	return 0;
+}
+
+static inline int ovl_dir_read_merged(struct path *upperpath,
+				      struct path *lowerpath,
+				      struct ovl_readdir_data *rdd)
+{
+	int err;
+	struct rb_root root = RB_ROOT;
+	struct list_head middle;
+
+	rdd->root = &root;
+	if (upperpath->dentry) {
+		rdd->dir = upperpath->dentry;
+		err = ovl_dir_read(upperpath, rdd, ovl_fill_upper);
+		if (err)
+			goto out;
+
+		err = ovl_dir_mark_whiteouts(rdd);
+		if (err)
+			goto out;
+	}
+	/*
+	 * Insert lowerpath entries before upperpath ones, this allows
+	 * offsets to be reasonably constant
+	 */
+	list_add(&middle, rdd->list);
+	rdd->middle = &middle;
+	err = ovl_dir_read(lowerpath, rdd, ovl_fill_lower);
+	list_del(&middle);
+out:
+	rdd->root = NULL;
+
+	return err;
+}
+
+static void ovl_seek_cursor(struct ovl_dir_file *od, loff_t pos)
+{
+	struct list_head *l;
+	loff_t off;
+
+	l = od->cache.next;
+	for (off = 0; off < pos; off++) {
+		if (l == &od->cache)
+			break;
+		l = l->next;
+	}
+	list_move_tail(&od->cursor, l);
+}
+
+static int ovl_readdir(struct file *file, void *buf, filldir_t filler)
+{
+	struct ovl_dir_file *od = file->private_data;
+	int res;
+
+	if (!file->f_pos)
+		ovl_dir_reset(file);
+
+	if (od->is_real) {
+		res = vfs_readdir(od->realfile, filler, buf);
+		file->f_pos = od->realfile->f_pos;
+
+		return res;
+	}
+
+	if (!od->is_cached) {
+		struct path lowerpath;
+		struct path upperpath;
+		struct ovl_readdir_data rdd = { .list = &od->cache };
+
+		ovl_path_lower(file->f_path.dentry, &lowerpath);
+		ovl_path_upper(file->f_path.dentry, &upperpath);
+
+		res = ovl_dir_read_merged(&upperpath, &lowerpath, &rdd);
+		if (res) {
+			ovl_cache_free(rdd.list);
+			return res;
+		}
+
+		od->cache_version = ovl_dentry_version_get(file->f_path.dentry);
+		od->is_cached = true;
+
+		ovl_seek_cursor(od, file->f_pos);
+	}
+
+	while (od->cursor.next != &od->cache) {
+		int over;
+		loff_t off;
+		struct ovl_cache_entry *p;
+
+		p = list_entry(od->cursor.next, struct ovl_cache_entry, l_node);
+		off = file->f_pos;
+		if (!p->is_whiteout) {
+			over = filler(buf, p->name, p->len, off, p->ino,
+				      p->type);
+			if (over)
+				break;
+		}
+		file->f_pos++;
+		list_move(&od->cursor, &p->l_node);
+	}
+
+	return 0;
+}
+
+static loff_t ovl_dir_llseek(struct file *file, loff_t offset, int origin)
+{
+	loff_t res;
+	struct ovl_dir_file *od = file->private_data;
+
+	mutex_lock(&file->f_dentry->d_inode->i_mutex);
+	if (!file->f_pos)
+		ovl_dir_reset(file);
+
+	if (od->is_real) {
+		res = vfs_llseek(od->realfile, offset, origin);
+		file->f_pos = od->realfile->f_pos;
+	} else {
+		res = -EINVAL;
+
+		switch (origin) {
+		case SEEK_CUR:
+			offset += file->f_pos;
+			break;
+		case SEEK_SET:
+			break;
+		default:
+			goto out_unlock;
+		}
+		if (offset < 0)
+			goto out_unlock;
+
+		if (offset != file->f_pos) {
+			file->f_pos = offset;
+			if (od->is_cached)
+				ovl_seek_cursor(od, offset);
+		}
+		res = offset;
+	}
+out_unlock:
+	mutex_unlock(&file->f_dentry->d_inode->i_mutex);
+
+	return res;
+}
+
+static int ovl_dir_fsync(struct file *file, loff_t start, loff_t end,
+			 int datasync)
+{
+	struct ovl_dir_file *od = file->private_data;
+
+	/* May need to reopen directory if it got copied up */
+	if (!od->realfile) {
+		struct path upperpath;
+
+		ovl_path_upper(file->f_path.dentry, &upperpath);
+		od->realfile = ovl_path_open(&upperpath, O_RDONLY);
+		if (IS_ERR(od->realfile))
+			return PTR_ERR(od->realfile);
+	}
+
+	return vfs_fsync_range(od->realfile, start, end, datasync);
+}
+
+static int ovl_dir_release(struct inode *inode, struct file *file)
+{
+	struct ovl_dir_file *od = file->private_data;
+
+	list_del(&od->cursor);
+	ovl_cache_free(&od->cache);
+	if (od->realfile)
+		fput(od->realfile);
+	kfree(od);
+
+	return 0;
+}
+
+static int ovl_dir_open(struct inode *inode, struct file *file)
+{
+	struct path realpath;
+	struct file *realfile;
+	struct ovl_dir_file *od;
+	enum ovl_path_type type;
+
+	od = kzalloc(sizeof(struct ovl_dir_file), GFP_KERNEL);
+	if (!od)
+		return -ENOMEM;
+
+	type = ovl_path_real(file->f_path.dentry, &realpath);
+	realfile = ovl_path_open(&realpath, file->f_flags);
+	if (IS_ERR(realfile)) {
+		kfree(od);
+		return PTR_ERR(realfile);
+	}
+	INIT_LIST_HEAD(&od->cache);
+	INIT_LIST_HEAD(&od->cursor);
+	od->is_cached = false;
+	od->realfile = realfile;
+	od->is_real = (type != OVL_PATH_MERGE);
+	file->private_data = od;
+
+	return 0;
+}
+
+const struct file_operations ovl_dir_operations = {
+	.read		= generic_read_dir,
+	.open		= ovl_dir_open,
+	.readdir	= ovl_readdir,
+	.llseek		= ovl_dir_llseek,
+	.fsync		= ovl_dir_fsync,
+	.release	= ovl_dir_release,
+};
+
+static int ovl_check_empty_dir(struct dentry *dentry, struct list_head *list)
+{
+	int err;
+	struct path lowerpath;
+	struct path upperpath;
+	struct ovl_cache_entry *p;
+	struct ovl_readdir_data rdd = { .list = list };
+
+	ovl_path_upper(dentry, &upperpath);
+	ovl_path_lower(dentry, &lowerpath);
+
+	err = ovl_dir_read_merged(&upperpath, &lowerpath, &rdd);
+	if (err)
+		return err;
+
+	err = 0;
+
+	list_for_each_entry(p, list, l_node) {
+		if (p->is_whiteout)
+			continue;
+
+		if (p->name[0] == '.') {
+			if (p->len == 1)
+				continue;
+			if (p->len == 2 && p->name[1] == '.')
+				continue;
+		}
+		err = -ENOTEMPTY;
+		break;
+	}
+
+	return err;
+}
+
+static int ovl_remove_whiteouts(struct dentry *dir, struct list_head *list)
+{
+	struct path upperpath;
+	struct dentry *upperdir;
+	struct ovl_cache_entry *p;
+	const struct cred *old_cred;
+	struct cred *override_cred;
+	int err;
+
+	ovl_path_upper(dir, &upperpath);
+	upperdir = upperpath.dentry;
+
+	override_cred = prepare_creds();
+	if (!override_cred)
+		return -ENOMEM;
+
+	/*
+	 * CAP_DAC_OVERRIDE for lookup and unlink
+	 * CAP_SYS_ADMIN for setxattr of "trusted" namespace
+	 * CAP_FOWNER for unlink in sticky directory
+	 */
+	cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE);
+	cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN);
+	cap_raise(override_cred->cap_effective, CAP_FOWNER);
+	old_cred = override_creds(override_cred);
+
+	err = vfs_setxattr(upperdir, ovl_opaque_xattr, "y", 1, 0);
+	if (err)
+		goto out_revert_creds;
+
+	mutex_lock_nested(&upperdir->d_inode->i_mutex, I_MUTEX_PARENT);
+	list_for_each_entry(p, list, l_node) {
+		struct dentry *dentry;
+		int ret;
+
+		if (!p->is_whiteout)
+			continue;
+
+		dentry = lookup_one_len(p->name, upperdir, p->len);
+		if (IS_ERR(dentry)) {
+			printk(KERN_WARNING
+			    "overlayfs: failed to lookup whiteout %.*s: %li\n",
+			    p->len, p->name, PTR_ERR(dentry));
+			continue;
+		}
+		ret = vfs_unlink(upperdir->d_inode, dentry);
+		dput(dentry);
+		if (ret)
+			printk(KERN_WARNING
+			    "overlayfs: failed to unlink whiteout %.*s: %i\n",
+			    p->len, p->name, ret);
+	}
+	mutex_unlock(&upperdir->d_inode->i_mutex);
+
+out_revert_creds:
+	revert_creds(old_cred);
+	put_cred(override_cred);
+
+	return err;
+}
+
+int ovl_check_empty_and_clear(struct dentry *dentry, enum ovl_path_type type)
+{
+	int err;
+	LIST_HEAD(list);
+
+	err = ovl_check_empty_dir(dentry, &list);
+	if (!err && type == OVL_PATH_MERGE)
+		err = ovl_remove_whiteouts(dentry, &list);
+
+	ovl_cache_free(&list);
+
+	return err;
+}
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
new file mode 100644
index 0000000..10cafe0
--- /dev/null
+++ b/fs/overlayfs/super.c
@@ -0,0 +1,664 @@
+/*
+ *
+ * Copyright (C) 2011 Novell 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/fs.h>
+#include <linux/namei.h>
+#include <linux/xattr.h>
+#include <linux/security.h>
+#include <linux/mount.h>
+#include <linux/slab.h>
+#include <linux/parser.h>
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include "overlayfs.h"
+
+MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>");
+MODULE_DESCRIPTION("Overlay filesystem");
+MODULE_LICENSE("GPL");
+
+struct ovl_config {
+	char *lowerdir;
+	char *upperdir;
+};
+
+/* private information held for overlayfs's superblock */
+struct ovl_fs {
+	struct vfsmount *upper_mnt;
+	struct vfsmount *lower_mnt;
+	/* pathnames of lower and upper dirs, for show_options */
+	struct ovl_config config;
+};
+
+/* private information held for every overlayfs dentry */
+struct ovl_entry {
+	/*
+	 * Keep "double reference" on upper dentries, so that
+	 * d_delete() doesn't think it's OK to reset d_inode to NULL.
+	 */
+	struct dentry *__upperdentry;
+	struct dentry *lowerdentry;
+	union {
+		struct {
+			u64 version;
+			bool opaque;
+		};
+		struct rcu_head rcu;
+	};
+};
+
+const char *ovl_whiteout_xattr = "trusted.overlay.whiteout";
+const char *ovl_opaque_xattr = "trusted.overlay.opaque";
+
+
+enum ovl_path_type ovl_path_type(struct dentry *dentry)
+{
+	struct ovl_entry *oe = dentry->d_fsdata;
+
+	if (oe->__upperdentry) {
+		if (oe->lowerdentry && S_ISDIR(dentry->d_inode->i_mode))
+			return OVL_PATH_MERGE;
+		else
+			return OVL_PATH_UPPER;
+	} else {
+		return OVL_PATH_LOWER;
+	}
+}
+
+static struct dentry *ovl_upperdentry_dereference(struct ovl_entry *oe)
+{
+	struct dentry *upperdentry = ACCESS_ONCE(oe->__upperdentry);
+	smp_read_barrier_depends();
+	return upperdentry;
+}
+
+void ovl_path_upper(struct dentry *dentry, struct path *path)
+{
+	struct ovl_fs *ofs = dentry->d_sb->s_fs_info;
+	struct ovl_entry *oe = dentry->d_fsdata;
+
+	path->mnt = ofs->upper_mnt;
+	path->dentry = ovl_upperdentry_dereference(oe);
+}
+
+void ovl_path_lower(struct dentry *dentry, struct path *path)
+{
+	struct ovl_fs *ofs = dentry->d_sb->s_fs_info;
+	struct ovl_entry *oe = dentry->d_fsdata;
+
+	path->mnt = ofs->lower_mnt;
+	path->dentry = oe->lowerdentry;
+}
+
+enum ovl_path_type ovl_path_real(struct dentry *dentry, struct path *path)
+{
+
+	enum ovl_path_type type = ovl_path_type(dentry);
+
+	if (type == OVL_PATH_LOWER)
+		ovl_path_lower(dentry, path);
+	else
+		ovl_path_upper(dentry, path);
+
+	return type;
+}
+
+struct dentry *ovl_dentry_upper(struct dentry *dentry)
+{
+	struct ovl_entry *oe = dentry->d_fsdata;
+
+	return ovl_upperdentry_dereference(oe);
+}
+
+struct dentry *ovl_dentry_lower(struct dentry *dentry)
+{
+	struct ovl_entry *oe = dentry->d_fsdata;
+
+	return oe->lowerdentry;
+}
+
+struct dentry *ovl_dentry_real(struct dentry *dentry)
+{
+	struct ovl_entry *oe = dentry->d_fsdata;
+	struct dentry *realdentry;
+
+	realdentry = ovl_upperdentry_dereference(oe);
+	if (!realdentry)
+		realdentry = oe->lowerdentry;
+
+	return realdentry;
+}
+
+struct dentry *ovl_entry_real(struct ovl_entry *oe, bool *is_upper)
+{
+	struct dentry *realdentry;
+
+	realdentry = ovl_upperdentry_dereference(oe);
+	if (realdentry) {
+		*is_upper = true;
+	} else {
+		realdentry = oe->lowerdentry;
+		*is_upper = false;
+	}
+	return realdentry;
+}
+
+bool ovl_dentry_is_opaque(struct dentry *dentry)
+{
+	struct ovl_entry *oe = dentry->d_fsdata;
+	return oe->opaque;
+}
+
+void ovl_dentry_set_opaque(struct dentry *dentry, bool opaque)
+{
+	struct ovl_entry *oe = dentry->d_fsdata;
+	oe->opaque = opaque;
+}
+
+void ovl_dentry_update(struct dentry *dentry, struct dentry *upperdentry)
+{
+	struct ovl_entry *oe = dentry->d_fsdata;
+
+	WARN_ON(!mutex_is_locked(&upperdentry->d_parent->d_inode->i_mutex));
+	WARN_ON(oe->__upperdentry);
+	BUG_ON(!upperdentry->d_inode);
+	smp_wmb();
+	oe->__upperdentry = dget(upperdentry);
+}
+
+void ovl_dentry_version_inc(struct dentry *dentry)
+{
+	struct ovl_entry *oe = dentry->d_fsdata;
+
+	WARN_ON(!mutex_is_locked(&dentry->d_inode->i_mutex));
+	oe->version++;
+}
+
+u64 ovl_dentry_version_get(struct dentry *dentry)
+{
+	struct ovl_entry *oe = dentry->d_fsdata;
+
+	WARN_ON(!mutex_is_locked(&dentry->d_inode->i_mutex));
+	return oe->version;
+}
+
+bool ovl_is_whiteout(struct dentry *dentry)
+{
+	int res;
+	char val;
+
+	if (!dentry)
+		return false;
+	if (!dentry->d_inode)
+		return false;
+	if (!S_ISLNK(dentry->d_inode->i_mode))
+		return false;
+
+	res = vfs_getxattr(dentry, ovl_whiteout_xattr, &val, 1);
+	if (res == 1 && val == 'y')
+		return true;
+
+	return false;
+}
+
+static bool ovl_is_opaquedir(struct dentry *dentry)
+{
+	int res;
+	char val;
+
+	if (!S_ISDIR(dentry->d_inode->i_mode))
+		return false;
+
+	res = vfs_getxattr(dentry, ovl_opaque_xattr, &val, 1);
+	if (res == 1 && val == 'y')
+		return true;
+
+	return false;
+}
+
+static void ovl_entry_free(struct rcu_head *head)
+{
+	struct ovl_entry *oe = container_of(head, struct ovl_entry, rcu);
+	kfree(oe);
+}
+
+static void ovl_dentry_release(struct dentry *dentry)
+{
+	struct ovl_entry *oe = dentry->d_fsdata;
+
+	if (oe) {
+		dput(oe->__upperdentry);
+		dput(oe->__upperdentry);
+		dput(oe->lowerdentry);
+		call_rcu(&oe->rcu, ovl_entry_free);
+	}
+}
+
+const struct dentry_operations ovl_dentry_operations = {
+	.d_release = ovl_dentry_release,
+};
+
+static struct ovl_entry *ovl_alloc_entry(void)
+{
+	return kzalloc(sizeof(struct ovl_entry), GFP_KERNEL);
+}
+
+static inline struct dentry *ovl_lookup_real(struct dentry *dir,
+					     struct qstr *name)
+{
+	struct dentry *dentry;
+
+	mutex_lock(&dir->d_inode->i_mutex);
+	dentry = lookup_one_len(name->name, dir, name->len);
+	mutex_unlock(&dir->d_inode->i_mutex);
+
+	if (IS_ERR(dentry)) {
+		if (PTR_ERR(dentry) == -ENOENT)
+			dentry = NULL;
+	} else if (!dentry->d_inode) {
+		dput(dentry);
+		dentry = NULL;
+	}
+	return dentry;
+}
+
+static int ovl_do_lookup(struct dentry *dentry)
+{
+	struct ovl_entry *oe;
+	struct dentry *upperdir;
+	struct dentry *lowerdir;
+	struct dentry *upperdentry = NULL;
+	struct dentry *lowerdentry = NULL;
+	struct inode *inode = NULL;
+	int err;
+
+	err = -ENOMEM;
+	oe = ovl_alloc_entry();
+	if (!oe)
+		goto out;
+
+	upperdir = ovl_dentry_upper(dentry->d_parent);
+	lowerdir = ovl_dentry_lower(dentry->d_parent);
+
+	if (upperdir) {
+		upperdentry = ovl_lookup_real(upperdir, &dentry->d_name);
+		err = PTR_ERR(upperdentry);
+		if (IS_ERR(upperdentry))
+			goto out_put_dir;
+
+		if (lowerdir && upperdentry &&
+		    (S_ISLNK(upperdentry->d_inode->i_mode) ||
+		     S_ISDIR(upperdentry->d_inode->i_mode))) {
+			const struct cred *old_cred;
+			struct cred *override_cred;
+
+			err = -ENOMEM;
+			override_cred = prepare_creds();
+			if (!override_cred)
+				goto out_dput_upper;
+
+			/* CAP_SYS_ADMIN needed for getxattr */
+			cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN);
+			old_cred = override_creds(override_cred);
+
+			if (ovl_is_opaquedir(upperdentry)) {
+				oe->opaque = true;
+			} else if (ovl_is_whiteout(upperdentry)) {
+				dput(upperdentry);
+				upperdentry = NULL;
+				oe->opaque = true;
+			}
+			revert_creds(old_cred);
+			put_cred(override_cred);
+		}
+	}
+	if (lowerdir && !oe->opaque) {
+		lowerdentry = ovl_lookup_real(lowerdir, &dentry->d_name);
+		err = PTR_ERR(lowerdentry);
+		if (IS_ERR(lowerdentry))
+			goto out_dput_upper;
+	}
+
+	if (lowerdentry && upperdentry &&
+	    (!S_ISDIR(upperdentry->d_inode->i_mode) ||
+	     !S_ISDIR(lowerdentry->d_inode->i_mode))) {
+		dput(lowerdentry);
+		lowerdentry = NULL;
+		oe->opaque = true;
+	}
+
+	if (lowerdentry || upperdentry) {
+		struct dentry *realdentry;
+
+		realdentry = upperdentry ? upperdentry : lowerdentry;
+		err = -ENOMEM;
+		inode = ovl_new_inode(dentry->d_sb, realdentry->d_inode->i_mode,
+				      oe);
+		if (!inode)
+			goto out_dput;
+	}
+
+	if (upperdentry)
+		oe->__upperdentry = dget(upperdentry);
+
+	if (lowerdentry)
+		oe->lowerdentry = lowerdentry;
+
+	dentry->d_fsdata = oe;
+	dentry->d_op = &ovl_dentry_operations;
+	d_add(dentry, inode);
+
+	return 0;
+
+out_dput:
+	dput(lowerdentry);
+out_dput_upper:
+	dput(upperdentry);
+out_put_dir:
+	kfree(oe);
+out:
+	return err;
+}
+
+struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
+			  struct nameidata *nd)
+{
+	int err = ovl_do_lookup(dentry);
+
+	if (err)
+		return ERR_PTR(err);
+
+	return NULL;
+}
+
+struct file *ovl_path_open(struct path *path, int flags)
+{
+	path_get(path);
+	return dentry_open(path->dentry, path->mnt, flags, current_cred());
+}
+
+static void ovl_put_super(struct super_block *sb)
+{
+	struct ovl_fs *ufs = sb->s_fs_info;
+
+	if (!(sb->s_flags & MS_RDONLY))
+		mnt_drop_write(ufs->upper_mnt);
+
+	mntput(ufs->upper_mnt);
+	mntput(ufs->lower_mnt);
+
+	kfree(ufs->config.lowerdir);
+	kfree(ufs->config.upperdir);
+	kfree(ufs);
+}
+
+static int ovl_remount_fs(struct super_block *sb, int *flagsp, char *data)
+{
+	int flags = *flagsp;
+	struct ovl_fs *ufs = sb->s_fs_info;
+
+	/* When remounting rw or ro, we need to adjust the write access to the
+	 * upper fs.
+	 */
+	if (((flags ^ sb->s_flags) & MS_RDONLY) == 0)
+		/* No change to readonly status */
+		return 0;
+
+	if (flags & MS_RDONLY) {
+		mnt_drop_write(ufs->upper_mnt);
+		return 0;
+	} else
+		return mnt_want_write(ufs->upper_mnt);
+}
+
+/**
+ * ovl_statfs
+ * @sb: The overlayfs super block
+ * @buf: The struct kstatfs to fill in with stats
+ *
+ * Get the filesystem statistics.  As writes always target the upper layer
+ * filesystem pass the statfs to the same filesystem.
+ */
+static int ovl_statfs(struct dentry *dentry, struct kstatfs *buf)
+{
+	struct dentry *root_dentry = dentry->d_sb->s_root;
+	struct path path;
+	ovl_path_upper(root_dentry, &path);
+
+	if (!path.dentry->d_sb->s_op->statfs)
+		return -ENOSYS;
+	return path.dentry->d_sb->s_op->statfs(path.dentry, buf);
+}
+
+/**
+ * ovl_show_options
+ *
+ * Prints the mount options for a given superblock.
+ * Returns zero; does not fail.
+ */
+static int ovl_show_options(struct seq_file *m, struct dentry *dentry)
+{
+	struct super_block *sb = dentry->d_sb;
+	struct ovl_fs *ufs = sb->s_fs_info;
+
+	seq_printf(m, ",lowerdir=%s", ufs->config.lowerdir);
+	seq_printf(m, ",upperdir=%s", ufs->config.upperdir);
+	return 0;
+}
+
+static const struct super_operations ovl_super_operations = {
+	.put_super	= ovl_put_super,
+	.remount_fs	= ovl_remount_fs,
+	.statfs		= ovl_statfs,
+	.show_options	= ovl_show_options,
+};
+
+enum {
+	Opt_lowerdir,
+	Opt_upperdir,
+	Opt_err,
+};
+
+static const match_table_t ovl_tokens = {
+	{Opt_lowerdir,			"lowerdir=%s"},
+	{Opt_upperdir,			"upperdir=%s"},
+	{Opt_err,			NULL}
+};
+
+static int ovl_parse_opt(char *opt, struct ovl_config *config)
+{
+	char *p;
+
+	config->upperdir = NULL;
+	config->lowerdir = NULL;
+
+	while ((p = strsep(&opt, ",")) != NULL) {
+		int token;
+		substring_t args[MAX_OPT_ARGS];
+
+		if (!*p)
+			continue;
+
+		token = match_token(p, ovl_tokens, args);
+		switch (token) {
+		case Opt_upperdir:
+			kfree(config->upperdir);
+			config->upperdir = match_strdup(&args[0]);
+			if (!config->upperdir)
+				return -ENOMEM;
+			break;
+
+		case Opt_lowerdir:
+			kfree(config->lowerdir);
+			config->lowerdir = match_strdup(&args[0]);
+			if (!config->lowerdir)
+				return -ENOMEM;
+			break;
+
+		default:
+			return -EINVAL;
+		}
+	}
+	return 0;
+}
+
+static int ovl_fill_super(struct super_block *sb, void *data, int silent)
+{
+	struct path lowerpath;
+	struct path upperpath;
+	struct inode *root_inode;
+	struct dentry *root_dentry;
+	struct ovl_entry *oe;
+	struct ovl_fs *ufs;
+	int err;
+
+	err = -ENOMEM;
+	ufs = kmalloc(sizeof(struct ovl_fs), GFP_KERNEL);
+	if (!ufs)
+		goto out;
+
+	err = ovl_parse_opt((char *) data, &ufs->config);
+	if (err)
+		goto out_free_ufs;
+
+	err = -EINVAL;
+	if (!ufs->config.upperdir || !ufs->config.lowerdir) {
+		printk(KERN_ERR "overlayfs: missing upperdir or lowerdir\n");
+		goto out_free_config;
+	}
+
+	oe = ovl_alloc_entry();
+	if (oe == NULL)
+		goto out_free_config;
+
+	root_inode = ovl_new_inode(sb, S_IFDIR, oe);
+	if (!root_inode)
+		goto out_free_oe;
+
+	err = kern_path(ufs->config.upperdir, LOOKUP_FOLLOW, &upperpath);
+	if (err)
+		goto out_put_root;
+
+	err = kern_path(ufs->config.lowerdir, LOOKUP_FOLLOW, &lowerpath);
+	if (err)
+		goto out_put_upperpath;
+
+	err = -ENOTDIR;
+	if (!S_ISDIR(upperpath.dentry->d_inode->i_mode) ||
+	    !S_ISDIR(lowerpath.dentry->d_inode->i_mode))
+		goto out_put_lowerpath;
+
+	sb->s_stack_depth = max(upperpath.mnt->mnt_sb->s_stack_depth,
+				lowerpath.mnt->mnt_sb->s_stack_depth) + 1;
+
+	err = -EINVAL;
+	if (sb->s_stack_depth > FILESYSTEM_MAX_STACK_DEPTH) {
+		printk(KERN_ERR "overlayfs: maximum fs stacking depth exceeded\n");
+		goto out_put_lowerpath;
+	}
+
+
+	ufs->upper_mnt = clone_private_mount(&upperpath);
+	err = PTR_ERR(ufs->upper_mnt);
+	if (IS_ERR(ufs->upper_mnt)) {
+		printk(KERN_ERR "overlayfs: failed to clone upperpath\n");
+		goto out_put_lowerpath;
+	}
+
+	ufs->lower_mnt = clone_private_mount(&lowerpath);
+	err = PTR_ERR(ufs->lower_mnt);
+	if (IS_ERR(ufs->lower_mnt)) {
+		printk(KERN_ERR "overlayfs: failed to clone lowerpath\n");
+		goto out_put_upper_mnt;
+	}
+
+	/*
+	 * Make lower_mnt R/O.  That way fchmod/fchown on lower file
+	 * will fail instead of modifying lower fs.
+	 */
+	ufs->lower_mnt->mnt_flags |= MNT_READONLY;
+
+	/* If the upper fs is r/o, we mark overlayfs r/o too */
+	if (ufs->upper_mnt->mnt_sb->s_flags & MS_RDONLY)
+		sb->s_flags |= MS_RDONLY;
+
+	if (!(sb->s_flags & MS_RDONLY)) {
+		err = mnt_want_write(ufs->upper_mnt);
+		if (err)
+			goto out_put_lower_mnt;
+	}
+
+	err = -ENOMEM;
+	root_dentry = d_alloc_root(root_inode);
+	if (!root_dentry)
+		goto out_drop_write;
+
+	mntput(upperpath.mnt);
+	mntput(lowerpath.mnt);
+
+	oe->__upperdentry = dget(upperpath.dentry);
+	oe->lowerdentry = lowerpath.dentry;
+
+	root_dentry->d_fsdata = oe;
+	root_dentry->d_op = &ovl_dentry_operations;
+
+	sb->s_op = &ovl_super_operations;
+	sb->s_root = root_dentry;
+	sb->s_fs_info = ufs;
+
+	return 0;
+
+out_drop_write:
+	if (!(sb->s_flags & MS_RDONLY))
+		mnt_drop_write(ufs->upper_mnt);
+out_put_lower_mnt:
+	mntput(ufs->lower_mnt);
+out_put_upper_mnt:
+	mntput(ufs->upper_mnt);
+out_put_lowerpath:
+	path_put(&lowerpath);
+out_put_upperpath:
+	path_put(&upperpath);
+out_put_root:
+	iput(root_inode);
+out_free_oe:
+	kfree(oe);
+out_free_config:
+	kfree(ufs->config.lowerdir);
+	kfree(ufs->config.upperdir);
+out_free_ufs:
+	kfree(ufs);
+out:
+	return err;
+}
+
+static struct dentry *ovl_mount(struct file_system_type *fs_type, int flags,
+				const char *dev_name, void *raw_data)
+{
+	return mount_nodev(fs_type, flags, raw_data, ovl_fill_super);
+}
+
+static struct file_system_type ovl_fs_type = {
+	.owner		= THIS_MODULE,
+	.name		= "overlayfs",
+	.mount		= ovl_mount,
+	.kill_sb	= kill_anon_super,
+};
+
+static int __init ovl_init(void)
+{
+	return register_filesystem(&ovl_fs_type);
+}
+
+static void __exit ovl_exit(void)
+{
+	unregister_filesystem(&ovl_fs_type);
+}
+
+module_init(ovl_init);
+module_exit(ovl_exit);
diff --git a/fs/splice.c b/fs/splice.c
index 96d7b28..544f86b 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -1302,6 +1302,7 @@
 
 	return ret;
 }
+EXPORT_SYMBOL(do_splice_direct);
 
 static int splice_pipe_to_pipe(struct pipe_inode_info *ipipe,
 			       struct pipe_inode_info *opipe,
diff --git a/fs/squashfs/xz_wrapper.c b/fs/squashfs/xz_wrapper.c
index 1760b7d1..790bdb5 100644
--- a/fs/squashfs/xz_wrapper.c
+++ b/fs/squashfs/xz_wrapper.c
@@ -39,8 +39,10 @@
 };
 
 struct comp_opts {
-	__le32 dictionary_size;
 	__le32 flags;
+	__le16 bit_opts;
+	__le16 fb;
+	__le32 dictionary_size;
 };
 
 static void *squashfs_xz_init(struct squashfs_sb_info *msblk, void *buff,
diff --git a/fs/ubifs/Kconfig b/fs/ubifs/Kconfig
index f8b0160..5934b99 100644
--- a/fs/ubifs/Kconfig
+++ b/fs/ubifs/Kconfig
@@ -5,8 +5,10 @@
 	select CRYPTO if UBIFS_FS_ADVANCED_COMPR
 	select CRYPTO if UBIFS_FS_LZO
 	select CRYPTO if UBIFS_FS_ZLIB
+	select CRYPTO if UBIFS_FS_XZ
 	select CRYPTO_LZO if UBIFS_FS_LZO
 	select CRYPTO_DEFLATE if UBIFS_FS_ZLIB
+	select CRYPTO_XZ if UBIFS_FS_XZ
 	depends on MTD_UBI
 	help
 	  UBIFS is a file system for flash devices which works on top of UBI.
@@ -42,6 +44,14 @@
 	help
 	  Zlib compresses better than LZO but it is slower. Say 'Y' if unsure.
 
+config UBIFS_FS_XZ
+	bool "XZ decompression support" if UBIFS_FS_ADVANCED_COMPR
+	depends on UBIFS_FS
+	default y
+	help
+	  XZ compresses better the ZLIB but it is slower. 
+	  Say 'Y' if unsure.
+
 # Debugging-related stuff
 config UBIFS_FS_DEBUG
 	bool "Enable debugging support"
diff --git a/fs/ubifs/compress.c b/fs/ubifs/compress.c
index 11e4132..a6e83b5 100644
--- a/fs/ubifs/compress.c
+++ b/fs/ubifs/compress.c
@@ -71,6 +71,24 @@
 };
 #endif
 
+#ifdef CONFIG_UBIFS_FS_XZ
+static DEFINE_MUTEX(xz_enc_mutex);
+static DEFINE_MUTEX(xz_dec_mutex);
+
+static struct ubifs_compressor xz_compr = {
+	.compr_type = UBIFS_COMPR_XZ,
+	.comp_mutex = &xz_enc_mutex,
+	.decomp_mutex = &xz_dec_mutex,
+	.name = "xz",
+	.capi_name = "xz",
+};
+#else
+static struct ubifs_compressor xz_compr = {
+	.compr_type = UBIFS_COMPR_XZ,
+	.name = "xz",
+};
+#endif
+
 /* All UBIFS compressors */
 struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT];
 
@@ -233,9 +251,15 @@
 	if (err)
 		goto out_lzo;
 
+	err = compr_init(&xz_compr);
+	if (err)
+		goto out_zlib;
+
 	ubifs_compressors[UBIFS_COMPR_NONE] = &none_compr;
 	return 0;
 
+out_zlib:
+	compr_exit(&zlib_compr);
 out_lzo:
 	compr_exit(&lzo_compr);
 	return err;
@@ -248,4 +272,5 @@
 {
 	compr_exit(&lzo_compr);
 	compr_exit(&zlib_compr);
+	compr_exit(&xz_compr);
 }
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index f9c234b..6b79020 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -1575,6 +1575,12 @@
 	.follow_link = ubifs_follow_link,
 	.setattr     = ubifs_setattr,
 	.getattr     = ubifs_getattr,
+#ifdef CONFIG_UBIFS_FS_XATTR
+	.setxattr    = ubifs_setxattr,
+	.getxattr    = ubifs_getxattr,
+	.listxattr   = ubifs_listxattr,
+	.removexattr = ubifs_removexattr,
+#endif
 };
 
 const struct file_operations ubifs_file_operations = {
diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c
index 2f438ab..b5de7b4 100644
--- a/fs/ubifs/journal.c
+++ b/fs/ubifs/journal.c
@@ -553,7 +553,8 @@
 
 	dbg_jnl("ino %lu, dent '%.*s', data len %d in dir ino %lu",
 		inode->i_ino, nm->len, nm->name, ui->data_len, dir->i_ino);
-	ubifs_assert(dir_ui->data_len == 0);
+	if (!xent)
+		ubifs_assert(dir_ui->data_len == 0);
 	ubifs_assert(mutex_is_locked(&dir_ui->ui_mutex));
 
 	dlen = UBIFS_DENT_NODE_SZ + nm->len + 1;
@@ -573,6 +574,13 @@
 	aligned_dlen = ALIGN(dlen, 8);
 	aligned_ilen = ALIGN(ilen, 8);
 	len = aligned_dlen + aligned_ilen + UBIFS_INO_NODE_SZ;
+	if (xent) {
+		/*
+		 * Make sure to account for dir_ui->data_len in
+		 * length calculation in case there is extended attribute.
+		 */
+		len += dir_ui->data_len;
+	}
 	dent = kmalloc(len, GFP_NOFS);
 	if (!dent)
 		return -ENOMEM;
@@ -649,7 +657,8 @@
 
 	ino_key_init(c, &ino_key, dir->i_ino);
 	ino_offs += aligned_ilen;
-	err = ubifs_tnc_add(c, &ino_key, lnum, ino_offs, UBIFS_INO_NODE_SZ);
+	err = ubifs_tnc_add(c, &ino_key, lnum, ino_offs,
+			    UBIFS_INO_NODE_SZ + dir_ui->data_len);
 	if (err)
 		goto out_ro;
 
diff --git a/fs/ubifs/ubifs-media.h b/fs/ubifs/ubifs-media.h
index e24380c..f85e3af 100644
--- a/fs/ubifs/ubifs-media.h
+++ b/fs/ubifs/ubifs-media.h
@@ -332,12 +332,14 @@
  * UBIFS_COMPR_NONE: no compression
  * UBIFS_COMPR_LZO: LZO compression
  * UBIFS_COMPR_ZLIB: ZLIB compression
+ * UBIFS_COMPR_XZ: XZ compression
  * UBIFS_COMPR_TYPES_CNT: count of supported compression types
  */
 enum {
 	UBIFS_COMPR_NONE,
 	UBIFS_COMPR_LZO,
 	UBIFS_COMPR_ZLIB,
+	UBIFS_COMPR_XZ,
 	UBIFS_COMPR_TYPES_CNT,
 };
 
diff --git a/fs/ubifs/xattr.c b/fs/ubifs/xattr.c
index 85b2722..b2efa4b 100644
--- a/fs/ubifs/xattr.c
+++ b/fs/ubifs/xattr.c
@@ -209,12 +209,12 @@
 		goto out_free;
 	}
 	inode->i_size = ui->ui_size = size;
-	ui->data_len = size;
 
 	mutex_lock(&host_ui->ui_mutex);
 	host->i_ctime = ubifs_current_time(host);
 	host_ui->xattr_size -= CALC_XATTR_BYTES(ui->data_len);
 	host_ui->xattr_size += CALC_XATTR_BYTES(size);
+	ui->data_len = size;
 
 	/*
 	 * It is important to write the host inode after the xattr inode
diff --git a/fs/yaffs2/yaffs_guts.c b/fs/yaffs2/yaffs_guts.c
index 36e11f5..19dcb65 100644
--- a/fs/yaffs2/yaffs_guts.c
+++ b/fs/yaffs2/yaffs_guts.c
@@ -1709,11 +1709,11 @@
 	}
 
 	/* TODO: Do we need this different handling for YAFFS2 and YAFFS1?? */
-	if (obj->my_dev->param.is_yaffs2)
+	// if (obj->my_dev->param.is_yaffs2) 
 		unlinkOp = (new_dir == obj->my_dev->unlinked_dir);
-	else
+	/* else
 		unlinkOp = (new_dir == obj->my_dev->unlinked_dir
-			    && obj->variant_type == YAFFS_OBJECT_TYPE_FILE);
+			    && obj->variant_type == YAFFS_OBJECT_TYPE_FILE); */
 
 	deleteOp = (new_dir == obj->my_dev->del_dir);
 
diff --git a/fs/yaffs2/yaffs_mtdif1.c b/fs/yaffs2/yaffs_mtdif1.c
index ca7b0a3..65d0bfb 100644
--- a/fs/yaffs2/yaffs_mtdif1.c
+++ b/fs/yaffs2/yaffs_mtdif1.c
@@ -34,6 +34,7 @@
 #include "linux/version.h"
 #include "linux/types.h"
 #include "linux/mtd/mtd.h"
+#include "mtd/mtd-abi.h"
 
 /* Don't compile this module if we don't have MTD's mtd_oob_ops interface */
 #if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17))
@@ -127,7 +128,7 @@
 #endif
 
 	memset(&ops, 0, sizeof(ops));
-	ops.mode = MTD_OOB_AUTO;
+	ops.mode = MTD_OPS_AUTO_OOB;
 	ops.len = (data) ? chunkBytes : 0;
 	ops.ooblen = YTAG1_SIZE;
 	ops.datbuf = (__u8 *)data;
@@ -179,7 +180,7 @@
 	int deleted;
 
 	memset(&ops, 0, sizeof(ops));
-	ops.mode = MTD_OOB_AUTO;
+	ops.mode = MTD_OPS_AUTO_OOB;
 	ops.len = (data) ? chunkBytes : 0;
 	ops.ooblen = YTAG1_SIZE;
 	ops.datbuf = data;
diff --git a/fs/yaffs2/yaffs_mtdif2.c b/fs/yaffs2/yaffs_mtdif2.c
index c6ebdaa..84d964fd 100644
--- a/fs/yaffs2/yaffs_mtdif2.c
+++ b/fs/yaffs2/yaffs_mtdif2.c
@@ -21,6 +21,7 @@
 #include "linux/mtd/mtd.h"
 #include "linux/types.h"
 #include "linux/time.h"
+#include "mtd/mtd-abi.h"
 
 #include "yaffs_packedtags2.h"
 
@@ -71,7 +72,7 @@
 		yaffs_PackTags2(&pt, tags, !dev->param.no_tags_ecc);
 
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
-	ops.mode = MTD_OOB_AUTO;
+	ops.mode = MTD_OPS_AUTO_OOB;
 	ops.ooblen = (dev->param.inband_tags) ? 0 : packed_tags_size;
 	ops.len = dev->param.total_bytes_per_chunk;
 	ops.ooboffs = 0;
@@ -136,7 +137,7 @@
 		retval = mtd->read(mtd, addr, dev->param.total_bytes_per_chunk,
 				&dummy, data);
 	else if (tags) {
-		ops.mode = MTD_OOB_AUTO;
+		ops.mode = MTD_OPS_AUTO_OOB;
 		ops.ooblen = packed_tags_size;
 		ops.len = data ? dev->data_bytes_per_chunk : packed_tags_size;
 		ops.ooboffs = 0;
diff --git a/fs/yaffs2/yaffs_vfs_glue.c b/fs/yaffs2/yaffs_vfs_glue.c
index 0f1ecee..369ceb8 100644
--- a/fs/yaffs2/yaffs_vfs_glue.c
+++ b/fs/yaffs2/yaffs_vfs_glue.c
@@ -72,7 +72,7 @@
 #include <linux/init.h>
 #include <linux/fs.h>
 #include <linux/proc_fs.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/pagemap.h>
 #include <linux/mtd/mtd.h>
 #include <linux/interrupt.h>
@@ -97,6 +97,8 @@
 
 #include <asm/div64.h>
 
+static DEFINE_MUTEX(yaffs_mutex);
+
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
 
 #include <linux/statfs.h>
@@ -218,11 +220,34 @@
 #define yaffs_SuperToDevice(sb)	((yaffs_dev_t *)sb->u.generic_sbp)
 #endif
 
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0))
+static inline void yaffs_set_nlink(struct inode *inode, unsigned int nlink)
+{
+	set_nlink(inode, nlink);
+}
+
+static inline void yaffs_dec_link_count(struct inode *inode)
+{
+	inode_dec_link_count(inode);
+}
+#else
+static inline void yaffs_set_nlink(struct inode *inode, unsigned int nlink)
+{
+	inode->i_nlink = nlink;
+}
+
+static inline void yaffs_dec_link_count(struct inode *inode)
+{
+	inode->i_nlink--;
+	mark_inode_dirty(inode)
+}
+#endif
+
 
 #define update_dir_time(dir) do {\
 			(dir)->i_ctime = (dir)->i_mtime = CURRENT_TIME; \
 		} while(0)
-		
+
 static void yaffs_put_super(struct super_block *sb);
 
 static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n,
@@ -236,7 +261,10 @@
 static int yaffs_file_flush(struct file *file);
 #endif
 
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 34))
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0))
+static int yaffs_sync_object(struct file *file, loff_t start, loff_t end,
+			     int datasync);
+#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 34))
 static int yaffs_sync_object(struct file *file, int datasync);
 #else
 static int yaffs_sync_object(struct file *file, struct dentry *dentry,
@@ -246,8 +274,13 @@
 static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir);
 
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
+static int yaffs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
+			struct nameidata *n);
+#else
 static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode,
 			struct nameidata *n);
+#endif
 static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry,
 					struct nameidata *n);
 #else
@@ -259,9 +292,17 @@
 static int yaffs_unlink(struct inode *dir, struct dentry *dentry);
 static int yaffs_symlink(struct inode *dir, struct dentry *dentry,
 			const char *symname);
-static int yaffs_mkdir(struct inode *dir, struct dentry *dentry, int mode);
 
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
+static int yaffs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode);
+#else
+static int yaffs_mkdir(struct inode *dir, struct dentry *dentry, int mode);
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
+static int yaffs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
+			dev_t dev);
+#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
 static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,
 			dev_t dev);
 #else
@@ -511,7 +552,7 @@
 {
 	return yaffs_gc_control;
 }
-                	                                                                                          	
+
 static void yaffs_gross_lock(yaffs_dev_t *dev)
 {
 	T(YAFFS_TRACE_LOCK, (TSTR("yaffs locking %p\n"), current));
@@ -1360,7 +1401,7 @@
 		inode->i_size = yaffs_get_obj_length(obj);
 		inode->i_blocks = (inode->i_size + 511) >> 9;
 
-		inode->i_nlink = yaffs_get_obj_link_count(obj);
+		yaffs_set_nlink(inode, yaffs_get_obj_link_count(obj));
 
 		T(YAFFS_TRACE_OS,
 			(TSTR("yaffs_fill_inode mode %x uid %d gid %d size %d count %d\n"),
@@ -1538,7 +1579,7 @@
 {
 	long long retval;
 
-	lock_kernel();
+	mutex_lock(&yaffs_mutex);
 
 	switch (origin){
 	case 2:
@@ -1555,7 +1596,7 @@
 
 		retval = offset;
 	}
-	unlock_kernel();
+	mutex_unlock(&yaffs_mutex);
 	return retval;
 }
 
@@ -1680,7 +1721,10 @@
 #define YCRED(x) (x->cred)
 #endif
 
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
+static int yaffs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
+			dev_t rdev)
+#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
 static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,
 			dev_t rdev)
 #else
@@ -1770,7 +1814,11 @@
 	return error;
 }
 
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
+static int yaffs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
+#else
 static int yaffs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+#endif
 {
 	int retVal;
 	T(YAFFS_TRACE_OS, (TSTR("yaffs_mkdir\n")));
@@ -1778,7 +1826,10 @@
 	return retVal;
 }
 
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
+static int yaffs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
+			struct nameidata *n)
+#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
 static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode,
 			struct nameidata *n)
 #else
@@ -1808,10 +1859,9 @@
 	retVal = yaffs_unlinker(obj, dentry->d_name.name);
 
 	if (retVal == YAFFS_OK) {
-		dentry->d_inode->i_nlink--;
+		yaffs_dec_link_count(dentry->d_inode);
 		dir->i_version++;
 		yaffs_gross_unlock(dev);
-		mark_inode_dirty(dentry->d_inode);
 		update_dir_time(dir);
 		return 0;
 	}
@@ -1842,7 +1892,8 @@
 			obj);
 
 	if (link) {
-		old_dentry->d_inode->i_nlink = yaffs_get_obj_link_count(obj);
+		yaffs_set_nlink(old_dentry->d_inode,
+				yaffs_get_obj_link_count(obj));
 		d_instantiate(dentry, old_dentry->d_inode);
 		atomic_inc(&old_dentry->d_inode->i_count);
 		T(YAFFS_TRACE_OS,
@@ -1892,7 +1943,10 @@
 	return -ENOMEM;
 }
 
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 34))
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0))
+static int yaffs_sync_object(struct file *file, loff_t start, loff_t end,
+			     int datasync)
+#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 34))
 static int yaffs_sync_object(struct file *file, int datasync)
 #else
 static int yaffs_sync_object(struct file *file, struct dentry *dentry,
@@ -1959,11 +2013,9 @@
 	yaffs_gross_unlock(dev);
 
 	if (retVal == YAFFS_OK) {
-		if (target) {
-			new_dentry->d_inode->i_nlink--;
-			mark_inode_dirty(new_dentry->d_inode);
-		}
-		
+		if (target)
+			yaffs_dec_link_count(new_dentry->d_inode);
+
 		update_dir_time(old_dir);
 		if(old_dir != new_dir)
 			update_dir_time(new_dir);
@@ -1983,7 +2035,7 @@
 		(TSTR("yaffs_setattr of object %d\n"),
 		yaffs_InodeToObject(inode)->obj_id));
 
-	/* Fail if a requested resize >= 2GB */		
+	/* Fail if a requested resize >= 2GB */
 	if (attr->ia_valid & ATTR_SIZE &&
 		(attr->ia_size >> 31))
 		error = -EINVAL;
@@ -2214,7 +2266,7 @@
 {
 	struct inode *iptr;
 	yaffs_obj_t *obj;
-	
+
 	list_for_each_entry(iptr,&sb->s_inodes, i_sb_list){
 		obj = yaffs_InodeToObject(iptr);
 		if(obj){
@@ -2228,10 +2280,10 @@
 
 static void yaffs_flush_super(struct super_block *sb, int do_checkpoint)
 {
-	yaffs_dev_t *dev = yaffs_SuperToDevice(sb);	
+	yaffs_dev_t *dev = yaffs_SuperToDevice(sb);
 	if(!dev)
 		return;
-	
+
 	yaffs_flush_inodes(sb);
 	yaffs_update_dirty_dirs(dev);
 	yaffs_flush_whole_cache(dev);
@@ -2299,7 +2351,7 @@
  * yaffs_bg_start() launches the background thread.
  * yaffs_bg_stop() cleans up the background thread.
  *
- * NB: 
+ * NB:
  * The thread should only run after the yaffs is initialised
  * The thread should be stopped before yaffs is unmounted.
  * The thread should not do any writing while the fs is in read only.
@@ -2870,7 +2922,7 @@
 
 	dev = kmalloc(sizeof(yaffs_dev_t), GFP_KERNEL);
 	context = kmalloc(sizeof(struct yaffs_LinuxContext),GFP_KERNEL);
-	
+
 	if(!dev || !context ){
 		if(dev)
 			kfree(dev);
@@ -2903,7 +2955,7 @@
 #else
 	sb->u.generic_sbp = dev;
 #endif
-	
+
 	dev->driver_context = mtd;
 	param->name = mtd->name;
 
@@ -3003,7 +3055,7 @@
 	param->gc_control = yaffs_gc_control_callback;
 
 	yaffs_dev_to_lc(dev)->superBlock= sb;
-	
+
 
 #ifndef CONFIG_YAFFS_DOES_ECC
 	param->use_nand_ecc = 1;
@@ -3036,7 +3088,7 @@
         YINIT_LIST_HEAD(&(yaffs_dev_to_lc(dev)->searchContexts));
         param->remove_obj_fn = yaffs_remove_obj_callback;
 
-	init_MUTEX(&(yaffs_dev_to_lc(dev)->grossLock));
+	sema_init(&(yaffs_dev_to_lc(dev)->grossLock), 1);
 
 	yaffs_gross_lock(dev);
 
@@ -3045,10 +3097,10 @@
 	T(YAFFS_TRACE_OS,
 	  (TSTR("yaffs_read_super: guts initialised %s\n"),
 	   (err == YAFFS_OK) ? "OK" : "FAILED"));
-	   
+
 	if(err == YAFFS_OK)
 		yaffs_bg_start(dev);
-		
+
 	if(!context->bgThread)
 		param->defered_dir_update = 0;
 
@@ -3087,98 +3139,52 @@
 	return sb;
 }
 
-
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
 static int yaffs_internal_read_super_mtd(struct super_block *sb, void *data,
 					 int silent)
 {
 	return yaffs_internal_read_super(1, sb, data, silent) ? 0 : -EINVAL;
 }
 
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
-static int yaffs_read_super(struct file_system_type *fs,
+static struct dentry *yaffs_read_super(struct file_system_type *fs,
 			    int flags, const char *dev_name,
-			    void *data, struct vfsmount *mnt)
+			    void *data)
 {
 
-	return get_sb_bdev(fs, flags, dev_name, data,
-			   yaffs_internal_read_super_mtd, mnt);
-}
-#else
-static struct super_block *yaffs_read_super(struct file_system_type *fs,
-					    int flags, const char *dev_name,
-					    void *data)
-{
-
-	return get_sb_bdev(fs, flags, dev_name, data,
+	return mount_bdev(fs, flags, dev_name, data,
 			   yaffs_internal_read_super_mtd);
 }
-#endif
 
 static struct file_system_type yaffs_fs_type = {
 	.owner = THIS_MODULE,
 	.name = "yaffs",
-	.get_sb = yaffs_read_super,
+	.mount = yaffs_read_super,
 	.kill_sb = kill_block_super,
 	.fs_flags = FS_REQUIRES_DEV,
 };
-#else
-static struct super_block *yaffs_read_super(struct super_block *sb, void *data,
-					    int silent)
-{
-	return yaffs_internal_read_super(1, sb, data, silent);
-}
-
-static DECLARE_FSTYPE(yaffs_fs_type, "yaffs", yaffs_read_super,
-		      FS_REQUIRES_DEV);
-#endif
-
 
 #ifdef CONFIG_YAFFS_YAFFS2
 
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
 static int yaffs2_internal_read_super_mtd(struct super_block *sb, void *data,
 					  int silent)
 {
 	return yaffs_internal_read_super(2, sb, data, silent) ? 0 : -EINVAL;
 }
 
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
-static int yaffs2_read_super(struct file_system_type *fs,
-			int flags, const char *dev_name, void *data,
-			struct vfsmount *mnt)
+static struct dentry *yaffs2_read_super(struct file_system_type *fs,
+			int flags, const char *dev_name,
+			void *data)
 {
-	return get_sb_bdev(fs, flags, dev_name, data,
-			yaffs2_internal_read_super_mtd, mnt);
+	return mount_bdev(fs, flags, dev_name, data,
+		yaffs2_internal_read_super_mtd);
 }
-#else
-static struct super_block *yaffs2_read_super(struct file_system_type *fs,
-					     int flags, const char *dev_name,
-					     void *data)
-{
-
-	return get_sb_bdev(fs, flags, dev_name, data,
-			   yaffs2_internal_read_super_mtd);
-}
-#endif
 
 static struct file_system_type yaffs2_fs_type = {
 	.owner = THIS_MODULE,
 	.name = "yaffs2",
-	.get_sb = yaffs2_read_super,
+	.mount = yaffs2_read_super,
 	.kill_sb = kill_block_super,
 	.fs_flags = FS_REQUIRES_DEV,
 };
-#else
-static struct super_block *yaffs2_read_super(struct super_block *sb,
-					     void *data, int silent)
-{
-	return yaffs_internal_read_super(2, sb, data, silent);
-}
-
-static DECLARE_FSTYPE(yaffs2_fs_type, "yaffs2", yaffs2_read_super,
-		      FS_REQUIRES_DEV);
-#endif
 
 #endif				/* CONFIG_YAFFS_YAFFS2 */
 
@@ -3267,7 +3273,7 @@
 		buf += sprintf(buf,"\n");
 	else {
 		step-=2;
-		
+
 		down(&yaffs_context_lock);
 
 		/* Locate and print the Nth entry.  Order N-squared but N is small. */
@@ -3284,7 +3290,7 @@
 				buf = yaffs_dump_dev_part0(buf, dev);
 			} else
 				buf = yaffs_dump_dev_part1(buf, dev);
-			
+
 			break;
 		}
 		up(&yaffs_context_lock);
@@ -3311,7 +3317,7 @@
 		int erasedChunks;
 
 		erasedChunks = dev->n_erased_blocks * dev->param.chunks_per_block;
-		
+
 		buf += sprintf(buf,"%d, %d, %d, %u, %u, %u, %u\n",
 				n, dev->n_free_chunks, erasedChunks,
 				dev->bg_gcs, dev->oldest_dirty_gc_count,
@@ -3494,7 +3500,7 @@
 
 
 
-	init_MUTEX(&yaffs_context_lock);
+	sema_init((&yaffs_context_lock), 1);
 
 	/* Install the proc_fs entries */
 	my_proc_entry = create_proc_entry("yaffs",
diff --git a/include/Kbuild b/include/Kbuild
index 8d226bf..eda7483 100644
--- a/include/Kbuild
+++ b/include/Kbuild
@@ -10,3 +10,4 @@
 header-y += drm/
 header-y += xen/
 header-y += scsi/
+header-y += net/
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index b5e2e4c..6935a59 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -52,6 +52,27 @@
 #define LOAD_OFFSET 0
 #endif
 
+#ifndef SYMTAB_KEEP_STR
+#define SYMTAB_KEEP_STR *(__ksymtab_strings+*)
+#define SYMTAB_DISCARD_STR
+#else
+#define SYMTAB_DISCARD_STR *(__ksymtab_strings+*)
+#endif
+
+#ifndef SYMTAB_KEEP
+#define SYMTAB_KEEP *(SORT(___ksymtab+*))
+#define SYMTAB_DISCARD
+#else
+#define SYMTAB_DISCARD *(SORT(___ksymtab+*))
+#endif
+
+#ifndef SYMTAB_KEEP_GPL
+#define SYMTAB_KEEP_GPL *(SORT(___ksymtab_gpl+*))
+#define SYMTAB_DISCARD_GPL
+#else
+#define SYMTAB_DISCARD_GPL *(SORT(___ksymtab_gpl+*))
+#endif
+
 #ifndef SYMBOL_PREFIX
 #define VMLINUX_SYMBOL(sym) sym
 #else
@@ -275,14 +296,14 @@
 	/* Kernel symbol table: Normal symbols */			\
 	__ksymtab         : AT(ADDR(__ksymtab) - LOAD_OFFSET) {		\
 		VMLINUX_SYMBOL(__start___ksymtab) = .;			\
-		*(SORT(___ksymtab+*))					\
+		SYMTAB_KEEP						\
 		VMLINUX_SYMBOL(__stop___ksymtab) = .;			\
 	}								\
 									\
 	/* Kernel symbol table: GPL-only symbols */			\
 	__ksymtab_gpl     : AT(ADDR(__ksymtab_gpl) - LOAD_OFFSET) {	\
 		VMLINUX_SYMBOL(__start___ksymtab_gpl) = .;		\
-		*(SORT(___ksymtab_gpl+*))				\
+		SYMTAB_KEEP_GPL						\
 		VMLINUX_SYMBOL(__stop___ksymtab_gpl) = .;		\
 	}								\
 									\
@@ -344,7 +365,7 @@
 									\
 	/* Kernel symbol table: strings */				\
         __ksymtab_strings : AT(ADDR(__ksymtab_strings) - LOAD_OFFSET) {	\
-		*(__ksymtab_strings)					\
+		SYMTAB_KEEP_STR						\
 	}								\
 									\
 	/* __*init sections */						\
@@ -676,6 +697,9 @@
 	EXIT_TEXT							\
 	EXIT_DATA							\
 	EXIT_CALL							\
+	SYMTAB_DISCARD							\
+	SYMTAB_DISCARD_GPL						\
+	SYMTAB_DISCARD_STR						\
 	*(.discard)							\
 	*(.discard.*)							\
 	}
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index c94e717..d5dc3c5 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -144,6 +144,8 @@
 header-y += genetlink.h
 header-y += gfs2_ondisk.h
 header-y += gigaset_dev.h
+header-y += glamofb.h
+header-y += glamo-engine.h
 header-y += hdlc.h
 header-y += hdlcdrv.h
 header-y += hdreg.h
diff --git a/include/linux/atm.h b/include/linux/atm.h
index d3b2921..2c63d27 100644
--- a/include/linux/atm.h
+++ b/include/linux/atm.h
@@ -139,6 +139,9 @@
 	int		min_pcr;	/* minimum PCR in cells per second */
 	int		max_cdv;	/* maximum CDV in microseconds */
 	int		max_sdu;	/* maximum SDU in bytes */
+	int		scr;		/* sustained rate in cells per second */
+	int		mbs;		/* maximum burst size (MBS) in cells */
+	int		cdv;		/* Cell delay varition */
         /* extra params for ABR */
         unsigned int 	icr;         	/* Initial Cell Rate (24-bit) */
         unsigned int	tbe;		/* Transient Buffer Exposure (24-bit) */ 
diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h
index f4ff882..7532f10 100644
--- a/include/linux/atmdev.h
+++ b/include/linux/atmdev.h
@@ -307,6 +307,7 @@
 	struct atm_dev	*dev;		/* device back pointer */
 	struct atm_qos	qos;		/* QOS */
 	struct atm_sap	sap;		/* SAP */
+	void (*release_cb)(struct atm_vcc *vcc); /* release_sock callback */
 	void (*push)(struct atm_vcc *vcc,struct sk_buff *skb);
 	void (*pop)(struct atm_vcc *vcc,struct sk_buff *skb); /* optional */
 	int (*push_oam)(struct atm_vcc *vcc,void *cell);
@@ -314,6 +315,7 @@
 	void		*dev_data;	/* per-device data */
 	void		*proto_data;	/* per-protocol data */
 	struct k_atm_aal_stats *stats;	/* pointer to AAL stats group */
+	struct module *owner;		/* owner of ->push function */
 	/* SVC part --- may move later ------------------------------------- */
 	short		itf;		/* interface number */
 	struct sockaddr_atmsvc local;
diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h
index 83c209f..1954a4e 100644
--- a/include/linux/bcma/bcma.h
+++ b/include/linux/bcma/bcma.h
@@ -7,6 +7,7 @@
 #include <linux/bcma/bcma_driver_chipcommon.h>
 #include <linux/bcma/bcma_driver_pci.h>
 #include <linux/bcma/bcma_driver_mips.h>
+#include <linux/bcma/bcma_driver_gmac_cmn.h>
 #include <linux/ssb/ssb.h> /* SPROM sharing */
 
 #include "bcma_regs.h"
@@ -26,6 +27,11 @@
 	u8 pkg;
 };
 
+struct bcma_boardinfo {
+	u16 vendor;
+	u16 type;
+};
+
 enum bcma_clkmode {
 	BCMA_CLKMODE_FAST,
 	BCMA_CLKMODE_DYNAMIC,
@@ -65,6 +71,13 @@
 
 /* Core-ID values. */
 #define BCMA_CORE_OOB_ROUTER		0x367	/* Out of band */
+#define BCMA_CORE_4706_CHIPCOMMON	0x500
+#define BCMA_CORE_4706_SOC_RAM		0x50E
+#define BCMA_CORE_4706_MAC_GBIT		0x52D
+#define BCMA_CORE_AMEMC			0x52E	/* DDR1/2 memory controller core */
+#define BCMA_CORE_ALTA			0x534	/* I2S core */
+#define BCMA_CORE_4706_MAC_GBIT_COMMON	0x5DC
+#define BCMA_CORE_DDR23_PHY		0x5DD
 #define BCMA_CORE_INVALID		0x700
 #define BCMA_CORE_CHIPCOMMON		0x800
 #define BCMA_CORE_ILINE20		0x801
@@ -125,6 +138,36 @@
 
 #define BCMA_MAX_NR_CORES		16
 
+/* Chip IDs of PCIe devices */
+#define BCMA_CHIP_ID_BCM4313	0x4313
+#define BCMA_CHIP_ID_BCM43224	43224
+#define  BCMA_PKG_ID_BCM43224_FAB_CSM	0x8
+#define  BCMA_PKG_ID_BCM43224_FAB_SMIC	0xa
+#define BCMA_CHIP_ID_BCM43225	43225
+#define BCMA_CHIP_ID_BCM43227	43227
+#define BCMA_CHIP_ID_BCM43228	43228
+#define BCMA_CHIP_ID_BCM43421	43421
+#define BCMA_CHIP_ID_BCM43428	43428
+#define BCMA_CHIP_ID_BCM43431	43431
+#define BCMA_CHIP_ID_BCM43460	43460
+#define BCMA_CHIP_ID_BCM4331	0x4331
+#define BCMA_CHIP_ID_BCM6362	0x6362
+#define BCMA_CHIP_ID_BCM4360	0x4360
+#define BCMA_CHIP_ID_BCM4352	0x4352
+
+/* Chip IDs of SoCs */
+#define BCMA_CHIP_ID_BCM4706	0x5300
+#define BCMA_CHIP_ID_BCM4716	0x4716
+#define  BCMA_PKG_ID_BCM4716	8
+#define  BCMA_PKG_ID_BCM4717	9
+#define  BCMA_PKG_ID_BCM4718	10
+#define BCMA_CHIP_ID_BCM47162	47162
+#define BCMA_CHIP_ID_BCM4748	0x4748
+#define BCMA_CHIP_ID_BCM4749	0x4749
+#define BCMA_CHIP_ID_BCM5356	0x5356
+#define BCMA_CHIP_ID_BCM5357	0x5357
+#define BCMA_CHIP_ID_BCM53572	53572
+
 struct bcma_device {
 	struct bcma_bus *bus;
 	struct bcma_device_id id;
@@ -136,8 +179,10 @@
 	bool dev_registered;
 
 	u8 core_index;
+	u8 core_unit;
 
 	u32 addr;
+	u32 addr1;
 	u32 wrap;
 
 	void __iomem *io_addr;
@@ -175,6 +220,12 @@
 
 extern void bcma_driver_unregister(struct bcma_driver *drv);
 
+/* Set a fallback SPROM.
+ * See kdoc at the function definition for complete documentation. */
+extern int bcma_arch_register_fallback_sprom(
+		int (*sprom_callback)(struct bcma_bus *bus,
+		struct ssb_sprom *out));
+
 struct bcma_bus {
 	/* The MMIO area. */
 	void __iomem *mmio;
@@ -191,14 +242,18 @@
 
 	struct bcma_chipinfo chipinfo;
 
+	struct bcma_boardinfo boardinfo;
+
 	struct bcma_device *mapped_core;
 	struct list_head cores;
 	u8 nr_cores;
 	u8 init_done:1;
+	u8 num;
 
 	struct bcma_drv_cc drv_cc;
 	struct bcma_drv_pci drv_pci;
 	struct bcma_drv_mips drv_mips;
+	struct bcma_drv_gmac_cmn drv_gmac_cmn;
 
 	/* We decided to share SPROM struct with SSB as long as we do not need
 	 * any hacks for BCMA. This simplifies drivers code. */
@@ -282,6 +337,7 @@
 	bcma_write16(cc, offset, (bcma_read16(cc, offset) & mask) | set);
 }
 
+extern struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid);
 extern bool bcma_core_is_enabled(struct bcma_device *core);
 extern void bcma_core_disable(struct bcma_device *core, u32 flags);
 extern int bcma_core_enable(struct bcma_device *core, u32 flags);
diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h
index a33086a..fbd0d49 100644
--- a/include/linux/bcma/bcma_driver_chipcommon.h
+++ b/include/linux/bcma/bcma_driver_chipcommon.h
@@ -56,6 +56,9 @@
 #define	 BCMA_CC_OTPS_HW_PROTECT	0x00000001
 #define	 BCMA_CC_OTPS_SW_PROTECT	0x00000002
 #define	 BCMA_CC_OTPS_CID_PROTECT	0x00000004
+#define  BCMA_CC_OTPS_GU_PROG_IND	0x00000F00	/* General Use programmed indication */
+#define  BCMA_CC_OTPS_GU_PROG_IND_SHIFT	8
+#define  BCMA_CC_OTPS_GU_PROG_HW	0x00000100	/* HW region programmed */
 #define BCMA_CC_OTPC			0x0014		/* OTP control */
 #define	 BCMA_CC_OTPC_RECWAIT		0xFF000000
 #define	 BCMA_CC_OTPC_PROGWAIT		0x00FFFF00
@@ -72,6 +75,8 @@
 #define	 BCMA_CC_OTPP_READ		0x40000000
 #define	 BCMA_CC_OTPP_START		0x80000000
 #define	 BCMA_CC_OTPP_BUSY		0x80000000
+#define BCMA_CC_OTPL			0x001C		/* OTP layout */
+#define  BCMA_CC_OTPL_GURGN_OFFSET	0x00000FFF	/* offset of general use region */
 #define BCMA_CC_IRQSTAT			0x0020
 #define BCMA_CC_IRQMASK			0x0024
 #define	 BCMA_CC_IRQ_GPIO		0x00000001	/* gpio intr */
@@ -79,6 +84,15 @@
 #define	 BCMA_CC_IRQ_WDRESET		0x80000000	/* watchdog reset occurred */
 #define BCMA_CC_CHIPCTL			0x0028		/* Rev >= 11 only */
 #define BCMA_CC_CHIPSTAT		0x002C		/* Rev >= 11 only */
+#define  BCMA_CC_CHIPST_4313_SPROM_PRESENT	1
+#define  BCMA_CC_CHIPST_4313_OTP_PRESENT	2
+#define  BCMA_CC_CHIPST_4331_SPROM_PRESENT	2
+#define  BCMA_CC_CHIPST_4331_OTP_PRESENT	4
+#define  BCMA_CC_CHIPST_4706_PKG_OPTION		BIT(0) /* 0: full-featured package 1: low-cost package */
+#define  BCMA_CC_CHIPST_4706_SFLASH_PRESENT	BIT(1) /* 0: parallel, 1: serial flash is present */
+#define  BCMA_CC_CHIPST_4706_SFLASH_TYPE	BIT(2) /* 0: 8b-p/ST-s flash, 1: 16b-p/Atmal-s flash */
+#define  BCMA_CC_CHIPST_4706_MIPS_BENDIAN	BIT(3) /* 0: little, 1: big endian */
+#define  BCMA_CC_CHIPST_4706_PCIE1_DISABLE	BIT(5) /* PCIE1 enable strap pin */
 #define BCMA_CC_JCMD			0x0030		/* Rev >= 10 only */
 #define  BCMA_CC_JCMD_START		0x80000000
 #define  BCMA_CC_JCMD_BUSY		0x80000000
@@ -181,6 +195,22 @@
 #define BCMA_CC_FLASH_CFG		0x0128
 #define  BCMA_CC_FLASH_CFG_DS		0x0010	/* Data size, 0=8bit, 1=16bit */
 #define BCMA_CC_FLASH_WAITCNT		0x012C
+#define BCMA_CC_SROM_CONTROL		0x0190
+#define  BCMA_CC_SROM_CONTROL_START	0x80000000
+#define  BCMA_CC_SROM_CONTROL_BUSY	0x80000000
+#define  BCMA_CC_SROM_CONTROL_OPCODE	0x60000000
+#define  BCMA_CC_SROM_CONTROL_OP_READ	0x00000000
+#define  BCMA_CC_SROM_CONTROL_OP_WRITE	0x20000000
+#define  BCMA_CC_SROM_CONTROL_OP_WRDIS	0x40000000
+#define  BCMA_CC_SROM_CONTROL_OP_WREN	0x60000000
+#define  BCMA_CC_SROM_CONTROL_OTPSEL	0x00000010
+#define  BCMA_CC_SROM_CONTROL_LOCK	0x00000008
+#define  BCMA_CC_SROM_CONTROL_SIZE_MASK	0x00000006
+#define  BCMA_CC_SROM_CONTROL_SIZE_1K	0x00000000
+#define  BCMA_CC_SROM_CONTROL_SIZE_4K	0x00000002
+#define  BCMA_CC_SROM_CONTROL_SIZE_16K	0x00000004
+#define  BCMA_CC_SROM_CONTROL_SIZE_SHIFT	1
+#define  BCMA_CC_SROM_CONTROL_PRESENT	0x00000001
 /* 0x1E0 is defined as shared BCMA_CLKCTLST */
 #define BCMA_CC_HW_WORKAROUND		0x01E4 /* Hardware workaround (rev >= 20) */
 #define BCMA_CC_UART0_DATA		0x0300
@@ -240,7 +270,6 @@
 #define BCMA_CC_PLLCTL_ADDR		0x0660
 #define BCMA_CC_PLLCTL_DATA		0x0664
 #define BCMA_CC_SPROM			0x0800 /* SPROM beginning */
-#define BCMA_CC_SPROM_PCIE6		0x0830 /* SPROM beginning on PCIe rev >= 6 */
 
 /* Divider allocation in 4716/47162/5356 */
 #define BCMA_CC_PMU5_MAINPLL_CPU	1
@@ -256,6 +285,15 @@
 
 /* 4706 PMU */
 #define BCMA_CC_PMU4706_MAINPLL_PLL0	0
+#define BCMA_CC_PMU6_4706_PROCPLL_OFF	4	/* The CPU PLL */
+#define  BCMA_CC_PMU6_4706_PROC_P2DIV_MASK	0x000f0000
+#define  BCMA_CC_PMU6_4706_PROC_P2DIV_SHIFT	16
+#define  BCMA_CC_PMU6_4706_PROC_P1DIV_MASK	0x0000f000
+#define  BCMA_CC_PMU6_4706_PROC_P1DIV_SHIFT	12
+#define  BCMA_CC_PMU6_4706_PROC_NDIV_INT_MASK	0x00000ff8
+#define  BCMA_CC_PMU6_4706_PROC_NDIV_INT_SHIFT	3
+#define  BCMA_CC_PMU6_4706_PROC_NDIV_MODE_MASK	0x00000007
+#define  BCMA_CC_PMU6_4706_PROC_NDIV_MODE_SHIFT	0
 
 /* ALP clock on pre-PMU chips */
 #define BCMA_CC_PMU_ALP_CLOCK		20000000
@@ -284,6 +322,19 @@
 #define BCMA_CC_PPL_PCHI_OFF		5
 #define BCMA_CC_PPL_PCHI_MASK		0x0000003f
 
+#define BCMA_CC_PMU_PLL_CTL0		0
+#define BCMA_CC_PMU_PLL_CTL1		1
+#define BCMA_CC_PMU_PLL_CTL2		2
+#define BCMA_CC_PMU_PLL_CTL3		3
+#define BCMA_CC_PMU_PLL_CTL4		4
+#define BCMA_CC_PMU_PLL_CTL5		5
+
+#define BCMA_CC_PMU1_PLL0_PC0_P1DIV_MASK	0x00f00000
+#define BCMA_CC_PMU1_PLL0_PC0_P1DIV_SHIFT	20
+
+#define BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_MASK	0x1ff00000
+#define BCMA_CC_PMU1_PLL0_PC2_NDIV_INT_SHIFT	20
+
 /* BCM4331 ChipControl numbers. */
 #define BCMA_CHIPCTL_4331_BT_COEXIST		BIT(0)	/* 0 disable */
 #define BCMA_CHIPCTL_4331_SECI			BIT(1)	/* 0 SECI is disabled (JATG functional) */
@@ -297,9 +348,18 @@
 #define BCMA_CHIPCTL_4331_OVR_PIPEAUXPWRDOWN	BIT(9)	/* override core control on pipe_AuxPowerDown */
 #define BCMA_CHIPCTL_4331_PCIE_AUXCLKEN		BIT(10)	/* pcie_auxclkenable */
 #define BCMA_CHIPCTL_4331_PCIE_PIPE_PLLDOWN	BIT(11)	/* pcie_pipe_pllpowerdown */
+#define BCMA_CHIPCTL_4331_EXTPA_EN2		BIT(12)	/* 0 ext pa disable, 1 ext pa enabled */
 #define BCMA_CHIPCTL_4331_BT_SHD0_ON_GPIO4	BIT(16)	/* enable bt_shd0 at gpio4 */
 #define BCMA_CHIPCTL_4331_BT_SHD1_ON_GPIO5	BIT(17)	/* enable bt_shd1 at gpio5 */
 
+/* 43224 chip-specific ChipControl register bits */
+#define BCMA_CCTRL_43224_GPIO_TOGGLE		0x8000		/* gpio[3:0] pins as btcoex or s/w gpio */
+#define BCMA_CCTRL_43224A0_12MA_LED_DRIVE	0x00F000F0	/* 12 mA drive strength */
+#define BCMA_CCTRL_43224B0_12MA_LED_DRIVE	0xF0		/* 12 mA drive strength for later 43224s */
+
+/* 4313 Chip specific ChipControl register bits */
+#define BCMA_CCTRL_4313_12MA_LED_DRIVE		0x00000007	/* 12 mA drive strengh for later 4313 */
+
 /* Data for the PMU, if available.
  * Check availability with ((struct bcma_chipcommon)->capabilities & BCMA_CC_CAP_PMU)
  */
@@ -387,5 +447,6 @@
 					u32 offset, u32 mask, u32 set);
 extern void bcma_chipco_regctl_maskset(struct bcma_drv_cc *cc,
 				       u32 offset, u32 mask, u32 set);
+extern void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid);
 
 #endif /* LINUX_BCMA_DRIVER_CC_H_ */
diff --git a/include/linux/bcma/bcma_driver_gmac_cmn.h b/include/linux/bcma/bcma_driver_gmac_cmn.h
new file mode 100644
index 0000000..def894b
--- /dev/null
+++ b/include/linux/bcma/bcma_driver_gmac_cmn.h
@@ -0,0 +1,100 @@
+#ifndef LINUX_BCMA_DRIVER_GMAC_CMN_H_
+#define LINUX_BCMA_DRIVER_GMAC_CMN_H_
+
+#include <linux/types.h>
+
+#define BCMA_GMAC_CMN_STAG0		0x000
+#define BCMA_GMAC_CMN_STAG1		0x004
+#define BCMA_GMAC_CMN_STAG2		0x008
+#define BCMA_GMAC_CMN_STAG3		0x00C
+#define BCMA_GMAC_CMN_PARSER_CTL	0x020
+#define BCMA_GMAC_CMN_MIB_MAX_LEN	0x024
+#define BCMA_GMAC_CMN_PHY_ACCESS	0x100
+#define  BCMA_GMAC_CMN_PA_DATA_MASK	0x0000ffff
+#define  BCMA_GMAC_CMN_PA_ADDR_MASK	0x001f0000
+#define  BCMA_GMAC_CMN_PA_ADDR_SHIFT	16
+#define  BCMA_GMAC_CMN_PA_REG_MASK	0x1f000000
+#define  BCMA_GMAC_CMN_PA_REG_SHIFT	24
+#define  BCMA_GMAC_CMN_PA_WRITE		0x20000000
+#define  BCMA_GMAC_CMN_PA_START		0x40000000
+#define BCMA_GMAC_CMN_PHY_CTL		0x104
+#define  BCMA_GMAC_CMN_PC_EPA_MASK	0x0000001f
+#define  BCMA_GMAC_CMN_PC_MCT_MASK	0x007f0000
+#define  BCMA_GMAC_CMN_PC_MCT_SHIFT	16
+#define  BCMA_GMAC_CMN_PC_MTE		0x00800000
+#define BCMA_GMAC_CMN_GMAC0_RGMII_CTL	0x110
+#define BCMA_GMAC_CMN_CFP_ACCESS	0x200
+#define BCMA_GMAC_CMN_CFP_TCAM_DATA0	0x210
+#define BCMA_GMAC_CMN_CFP_TCAM_DATA1	0x214
+#define BCMA_GMAC_CMN_CFP_TCAM_DATA2	0x218
+#define BCMA_GMAC_CMN_CFP_TCAM_DATA3	0x21C
+#define BCMA_GMAC_CMN_CFP_TCAM_DATA4	0x220
+#define BCMA_GMAC_CMN_CFP_TCAM_DATA5	0x224
+#define BCMA_GMAC_CMN_CFP_TCAM_DATA6	0x228
+#define BCMA_GMAC_CMN_CFP_TCAM_DATA7	0x22C
+#define BCMA_GMAC_CMN_CFP_TCAM_MASK0	0x230
+#define BCMA_GMAC_CMN_CFP_TCAM_MASK1	0x234
+#define BCMA_GMAC_CMN_CFP_TCAM_MASK2	0x238
+#define BCMA_GMAC_CMN_CFP_TCAM_MASK3	0x23C
+#define BCMA_GMAC_CMN_CFP_TCAM_MASK4	0x240
+#define BCMA_GMAC_CMN_CFP_TCAM_MASK5	0x244
+#define BCMA_GMAC_CMN_CFP_TCAM_MASK6	0x248
+#define BCMA_GMAC_CMN_CFP_TCAM_MASK7	0x24C
+#define BCMA_GMAC_CMN_CFP_ACTION_DATA	0x250
+#define BCMA_GMAC_CMN_TCAM_BIST_CTL	0x2A0
+#define BCMA_GMAC_CMN_TCAM_BIST_STATUS	0x2A4
+#define BCMA_GMAC_CMN_TCAM_CMP_STATUS	0x2A8
+#define BCMA_GMAC_CMN_TCAM_DISABLE	0x2AC
+#define BCMA_GMAC_CMN_TCAM_TEST_CTL	0x2F0
+#define BCMA_GMAC_CMN_UDF_0_A3_A0	0x300
+#define BCMA_GMAC_CMN_UDF_0_A7_A4	0x304
+#define BCMA_GMAC_CMN_UDF_0_A8		0x308
+#define BCMA_GMAC_CMN_UDF_1_A3_A0	0x310
+#define BCMA_GMAC_CMN_UDF_1_A7_A4	0x314
+#define BCMA_GMAC_CMN_UDF_1_A8		0x318
+#define BCMA_GMAC_CMN_UDF_2_A3_A0	0x320
+#define BCMA_GMAC_CMN_UDF_2_A7_A4	0x324
+#define BCMA_GMAC_CMN_UDF_2_A8		0x328
+#define BCMA_GMAC_CMN_UDF_0_B3_B0	0x330
+#define BCMA_GMAC_CMN_UDF_0_B7_B4	0x334
+#define BCMA_GMAC_CMN_UDF_0_B8		0x338
+#define BCMA_GMAC_CMN_UDF_1_B3_B0	0x340
+#define BCMA_GMAC_CMN_UDF_1_B7_B4	0x344
+#define BCMA_GMAC_CMN_UDF_1_B8		0x348
+#define BCMA_GMAC_CMN_UDF_2_B3_B0	0x350
+#define BCMA_GMAC_CMN_UDF_2_B7_B4	0x354
+#define BCMA_GMAC_CMN_UDF_2_B8		0x358
+#define BCMA_GMAC_CMN_UDF_0_C3_C0	0x360
+#define BCMA_GMAC_CMN_UDF_0_C7_C4	0x364
+#define BCMA_GMAC_CMN_UDF_0_C8		0x368
+#define BCMA_GMAC_CMN_UDF_1_C3_C0	0x370
+#define BCMA_GMAC_CMN_UDF_1_C7_C4	0x374
+#define BCMA_GMAC_CMN_UDF_1_C8		0x378
+#define BCMA_GMAC_CMN_UDF_2_C3_C0	0x380
+#define BCMA_GMAC_CMN_UDF_2_C7_C4	0x384
+#define BCMA_GMAC_CMN_UDF_2_C8		0x388
+#define BCMA_GMAC_CMN_UDF_0_D3_D0	0x390
+#define BCMA_GMAC_CMN_UDF_0_D7_D4	0x394
+#define BCMA_GMAC_CMN_UDF_0_D11_D8	0x394
+
+struct bcma_drv_gmac_cmn {
+	struct bcma_device *core;
+
+	/* Drivers accessing BCMA_GMAC_CMN_PHY_ACCESS and
+	 * BCMA_GMAC_CMN_PHY_CTL need to take that mutex first. */
+	struct mutex phy_mutex;
+};
+
+/* Register access */
+#define gmac_cmn_read16(gc, offset)		bcma_read16((gc)->core, offset)
+#define gmac_cmn_read32(gc, offset)		bcma_read32((gc)->core, offset)
+#define gmac_cmn_write16(gc, offset, val)	bcma_write16((gc)->core, offset, val)
+#define gmac_cmn_write32(gc, offset, val)	bcma_write32((gc)->core, offset, val)
+
+#ifdef CONFIG_BCMA_DRIVER_GMAC_CMN
+extern void __devinit bcma_core_gmac_cmn_init(struct bcma_drv_gmac_cmn *gc);
+#else
+static inline void bcma_core_gmac_cmn_init(struct bcma_drv_gmac_cmn *gc) { }
+#endif
+
+#endif /* LINUX_BCMA_DRIVER_GMAC_CMN_H_ */
diff --git a/include/linux/bcma/bcma_driver_pci.h b/include/linux/bcma/bcma_driver_pci.h
index 3871b66..41da581 100644
--- a/include/linux/bcma/bcma_driver_pci.h
+++ b/include/linux/bcma/bcma_driver_pci.h
@@ -53,11 +53,47 @@
 #define  BCMA_CORE_PCI_SBTOPCI1_MASK		0xFC000000
 #define BCMA_CORE_PCI_SBTOPCI2			0x0108	/* Backplane to PCI translation 2 (sbtopci2) */
 #define  BCMA_CORE_PCI_SBTOPCI2_MASK		0xC0000000
+#define BCMA_CORE_PCI_CONFIG_ADDR		0x0120	/* pcie config space access */
+#define BCMA_CORE_PCI_CONFIG_DATA		0x0124	/* pcie config space access */
+#define BCMA_CORE_PCI_MDIO_CONTROL		0x0128	/* controls the mdio access */
+#define  BCMA_CORE_PCI_MDIOCTL_DIVISOR_MASK	0x7f	/* clock to be used on MDIO */
+#define  BCMA_CORE_PCI_MDIOCTL_DIVISOR_VAL	0x2
+#define  BCMA_CORE_PCI_MDIOCTL_PREAM_EN		0x80	/* Enable preamble sequnce */
+#define  BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE	0x100	/* Tranaction complete */
+#define BCMA_CORE_PCI_MDIO_DATA			0x012c	/* Data to the mdio access */
+#define  BCMA_CORE_PCI_MDIODATA_MASK		0x0000ffff /* data 2 bytes */
+#define  BCMA_CORE_PCI_MDIODATA_TA		0x00020000 /* Turnaround */
+#define  BCMA_CORE_PCI_MDIODATA_REGADDR_SHF_OLD	18	/* Regaddr shift (rev < 10) */
+#define  BCMA_CORE_PCI_MDIODATA_REGADDR_MASK_OLD	0x003c0000 /* Regaddr Mask (rev < 10) */
+#define  BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF_OLD	22	/* Physmedia devaddr shift (rev < 10) */
+#define  BCMA_CORE_PCI_MDIODATA_DEVADDR_MASK_OLD	0x0fc00000 /* Physmedia devaddr Mask (rev < 10) */
+#define  BCMA_CORE_PCI_MDIODATA_REGADDR_SHF	18	/* Regaddr shift */
+#define  BCMA_CORE_PCI_MDIODATA_REGADDR_MASK	0x007c0000 /* Regaddr Mask */
+#define  BCMA_CORE_PCI_MDIODATA_DEVADDR_SHF	23	/* Physmedia devaddr shift */
+#define  BCMA_CORE_PCI_MDIODATA_DEVADDR_MASK	0x0f800000 /* Physmedia devaddr Mask */
+#define  BCMA_CORE_PCI_MDIODATA_WRITE		0x10000000 /* write Transaction */
+#define  BCMA_CORE_PCI_MDIODATA_READ		0x20000000 /* Read Transaction */
+#define  BCMA_CORE_PCI_MDIODATA_START		0x40000000 /* start of Transaction */
+#define  BCMA_CORE_PCI_MDIODATA_DEV_ADDR	0x0	/* dev address for serdes */
+#define  BCMA_CORE_PCI_MDIODATA_BLK_ADDR	0x1F	/* blk address for serdes */
+#define  BCMA_CORE_PCI_MDIODATA_DEV_PLL		0x1d	/* SERDES PLL Dev */
+#define  BCMA_CORE_PCI_MDIODATA_DEV_TX		0x1e	/* SERDES TX Dev */
+#define  BCMA_CORE_PCI_MDIODATA_DEV_RX		0x1f	/* SERDES RX Dev */
+#define BCMA_CORE_PCI_PCIEIND_ADDR		0x0130	/* indirect access to the internal register */
+#define BCMA_CORE_PCI_PCIEIND_DATA		0x0134	/* Data to/from the internal regsiter */
+#define BCMA_CORE_PCI_CLKREQENCTRL		0x0138	/*  >= rev 6, Clkreq rdma control */
 #define BCMA_CORE_PCI_PCICFG0			0x0400	/* PCI config space 0 (rev >= 8) */
 #define BCMA_CORE_PCI_PCICFG1			0x0500	/* PCI config space 1 (rev >= 8) */
 #define BCMA_CORE_PCI_PCICFG2			0x0600	/* PCI config space 2 (rev >= 8) */
 #define BCMA_CORE_PCI_PCICFG3			0x0700	/* PCI config space 3 (rev >= 8) */
 #define BCMA_CORE_PCI_SPROM(wordoffset)		(0x0800 + ((wordoffset) * 2)) /* SPROM shadow area (72 bytes) */
+#define  BCMA_CORE_PCI_SPROM_PI_OFFSET		0	/* first word */
+#define   BCMA_CORE_PCI_SPROM_PI_MASK		0xf000	/* bit 15:12 */
+#define   BCMA_CORE_PCI_SPROM_PI_SHIFT		12	/* bit 15:12 */
+#define  BCMA_CORE_PCI_SPROM_MISC_CONFIG	5	/* word 5 */
+#define   BCMA_CORE_PCI_SPROM_L23READY_EXIT_NOPERST	0x8000	/* bit 15 */
+#define   BCMA_CORE_PCI_SPROM_CLKREQ_OFFSET_REV5	20	/* word 20 for srom rev <= 5 */
+#define   BCMA_CORE_PCI_SPROM_CLKREQ_ENB	0x0800	/* bit 11 */
 
 /* SBtoPCIx */
 #define BCMA_CORE_PCI_SBTOPCI_MEM		0x00000000
@@ -72,20 +108,118 @@
 #define  BCMA_CORE_PCI_SBTOPCI_RC_READL		0x00000010 /* Memory read line */
 #define  BCMA_CORE_PCI_SBTOPCI_RC_READM		0x00000020 /* Memory read multiple */
 
+/* PCIE protocol PHY diagnostic registers */
+#define BCMA_CORE_PCI_PLP_MODEREG		0x200	/* Mode */
+#define BCMA_CORE_PCI_PLP_STATUSREG		0x204	/* Status */
+#define  BCMA_CORE_PCI_PLP_POLARITYINV_STAT	0x10	/* Status reg PCIE_PLP_STATUSREG */
+#define BCMA_CORE_PCI_PLP_LTSSMCTRLREG		0x208	/* LTSSM control */
+#define BCMA_CORE_PCI_PLP_LTLINKNUMREG		0x20c	/* Link Training Link number */
+#define BCMA_CORE_PCI_PLP_LTLANENUMREG		0x210	/* Link Training Lane number */
+#define BCMA_CORE_PCI_PLP_LTNFTSREG		0x214	/* Link Training N_FTS */
+#define BCMA_CORE_PCI_PLP_ATTNREG		0x218	/* Attention */
+#define BCMA_CORE_PCI_PLP_ATTNMASKREG		0x21C	/* Attention Mask */
+#define BCMA_CORE_PCI_PLP_RXERRCTR		0x220	/* Rx Error */
+#define BCMA_CORE_PCI_PLP_RXFRMERRCTR		0x224	/* Rx Framing Error */
+#define BCMA_CORE_PCI_PLP_RXERRTHRESHREG	0x228	/* Rx Error threshold */
+#define BCMA_CORE_PCI_PLP_TESTCTRLREG		0x22C	/* Test Control reg */
+#define BCMA_CORE_PCI_PLP_SERDESCTRLOVRDREG	0x230	/* SERDES Control Override */
+#define BCMA_CORE_PCI_PLP_TIMINGOVRDREG		0x234	/* Timing param override */
+#define BCMA_CORE_PCI_PLP_RXTXSMDIAGREG		0x238	/* RXTX State Machine Diag */
+#define BCMA_CORE_PCI_PLP_LTSSMDIAGREG		0x23C	/* LTSSM State Machine Diag */
+
+/* PCIE protocol DLLP diagnostic registers */
+#define BCMA_CORE_PCI_DLLP_LCREG		0x100	/* Link Control */
+#define BCMA_CORE_PCI_DLLP_LSREG		0x104	/* Link Status */
+#define BCMA_CORE_PCI_DLLP_LAREG		0x108	/* Link Attention */
+#define  BCMA_CORE_PCI_DLLP_LSREG_LINKUP	(1 << 16)
+#define BCMA_CORE_PCI_DLLP_LAMASKREG		0x10C	/* Link Attention Mask */
+#define BCMA_CORE_PCI_DLLP_NEXTTXSEQNUMREG	0x110	/* Next Tx Seq Num */
+#define BCMA_CORE_PCI_DLLP_ACKEDTXSEQNUMREG	0x114	/* Acked Tx Seq Num */
+#define BCMA_CORE_PCI_DLLP_PURGEDTXSEQNUMREG	0x118	/* Purged Tx Seq Num */
+#define BCMA_CORE_PCI_DLLP_RXSEQNUMREG		0x11C	/* Rx Sequence Number */
+#define BCMA_CORE_PCI_DLLP_LRREG		0x120	/* Link Replay */
+#define BCMA_CORE_PCI_DLLP_LACKTOREG		0x124	/* Link Ack Timeout */
+#define BCMA_CORE_PCI_DLLP_PMTHRESHREG		0x128	/* Power Management Threshold */
+#define  BCMA_CORE_PCI_ASPMTIMER_EXTEND		0x01000000 /* > rev7: enable extend ASPM timer */
+#define BCMA_CORE_PCI_DLLP_RTRYWPREG		0x12C	/* Retry buffer write ptr */
+#define BCMA_CORE_PCI_DLLP_RTRYRPREG		0x130	/* Retry buffer Read ptr */
+#define BCMA_CORE_PCI_DLLP_RTRYPPREG		0x134	/* Retry buffer Purged ptr */
+#define BCMA_CORE_PCI_DLLP_RTRRWREG		0x138	/* Retry buffer Read/Write */
+#define BCMA_CORE_PCI_DLLP_ECTHRESHREG		0x13C	/* Error Count Threshold */
+#define BCMA_CORE_PCI_DLLP_TLPERRCTRREG		0x140	/* TLP Error Counter */
+#define BCMA_CORE_PCI_DLLP_ERRCTRREG		0x144	/* Error Counter */
+#define BCMA_CORE_PCI_DLLP_NAKRXCTRREG		0x148	/* NAK Received Counter */
+#define BCMA_CORE_PCI_DLLP_TESTREG		0x14C	/* Test */
+#define BCMA_CORE_PCI_DLLP_PKTBIST		0x150	/* Packet BIST */
+#define BCMA_CORE_PCI_DLLP_PCIE11		0x154	/* DLLP PCIE 1.1 reg */
+
+/* SERDES RX registers */
+#define BCMA_CORE_PCI_SERDES_RX_CTRL		1	/* Rx cntrl */
+#define  BCMA_CORE_PCI_SERDES_RX_CTRL_FORCE	0x80	/* rxpolarity_force */
+#define  BCMA_CORE_PCI_SERDES_RX_CTRL_POLARITY	0x40	/* rxpolarity_value */
+#define BCMA_CORE_PCI_SERDES_RX_TIMER1		2	/* Rx Timer1 */
+#define BCMA_CORE_PCI_SERDES_RX_CDR		6	/* CDR */
+#define BCMA_CORE_PCI_SERDES_RX_CDRBW		7	/* CDR BW */
+
+/* SERDES PLL registers */
+#define BCMA_CORE_PCI_SERDES_PLL_CTRL		1	/* PLL control reg */
+#define BCMA_CORE_PCI_PLL_CTRL_FREQDET_EN	0x4000	/* bit 14 is FREQDET on */
+
 /* PCIcore specific boardflags */
 #define BCMA_CORE_PCI_BFL_NOPCI			0x00000400 /* Board leaves PCI floating */
 
+/* PCIE Config space accessing MACROS */
+#define BCMA_CORE_PCI_CFG_BUS_SHIFT		24	/* Bus shift */
+#define BCMA_CORE_PCI_CFG_SLOT_SHIFT		19	/* Slot/Device shift */
+#define BCMA_CORE_PCI_CFG_FUN_SHIFT		16	/* Function shift */
+#define BCMA_CORE_PCI_CFG_OFF_SHIFT		0	/* Register shift */
+
+#define BCMA_CORE_PCI_CFG_BUS_MASK		0xff	/* Bus mask */
+#define BCMA_CORE_PCI_CFG_SLOT_MASK		0x1f	/* Slot/Device mask */
+#define BCMA_CORE_PCI_CFG_FUN_MASK		7	/* Function mask */
+#define BCMA_CORE_PCI_CFG_OFF_MASK		0xfff	/* Register mask */
+
+/* PCIE Root Capability Register bits (Host mode only) */
+#define BCMA_CORE_PCI_RC_CRS_VISIBILITY		0x0001
+
+struct bcma_drv_pci;
+
+#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
+struct bcma_drv_pci_host {
+	struct bcma_drv_pci *pdev;
+
+	u32 host_cfg_addr;
+	spinlock_t cfgspace_lock;
+
+	struct pci_controller pci_controller;
+	struct pci_ops pci_ops;
+	struct resource mem_resource;
+	struct resource io_resource;
+};
+#endif
+
 struct bcma_drv_pci {
 	struct bcma_device *core;
 	u8 setup_done:1;
+	u8 hostmode:1;
+
+#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
+	struct bcma_drv_pci_host *host_controller;
+#endif
 };
 
 /* Register access */
+#define pcicore_read16(pc, offset)		bcma_read16((pc)->core, offset)
 #define pcicore_read32(pc, offset)		bcma_read32((pc)->core, offset)
+#define pcicore_write16(pc, offset, val)	bcma_write16((pc)->core, offset, val)
 #define pcicore_write32(pc, offset, val)	bcma_write32((pc)->core, offset, val)
 
-extern void bcma_core_pci_init(struct bcma_drv_pci *pc);
+extern void __devinit bcma_core_pci_init(struct bcma_drv_pci *pc);
 extern int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc,
 				 struct bcma_device *core, bool enable);
+extern void bcma_core_pci_extend_L1timer(struct bcma_drv_pci *pc, bool extend);
+
+extern int bcma_core_pci_pcibios_map_irq(const struct pci_dev *dev);
+extern int bcma_core_pci_plat_dev_init(struct pci_dev *dev);
 
 #endif /* LINUX_BCMA_DRIVER_PCI_H_ */
diff --git a/include/linux/bcma/bcma_regs.h b/include/linux/bcma/bcma_regs.h
index 9faae2a..5a71d57 100644
--- a/include/linux/bcma/bcma_regs.h
+++ b/include/linux/bcma/bcma_regs.h
@@ -56,4 +56,31 @@
 #define  BCMA_PCI_GPIO_XTAL		0x40	/* PCI config space GPIO 14 for Xtal powerup */
 #define  BCMA_PCI_GPIO_PLL		0x80	/* PCI config space GPIO 15 for PLL powerdown */
 
+/* SiliconBackplane Address Map.
+ * All regions may not exist on all chips.
+ */
+#define BCMA_SOC_SDRAM_BASE		0x00000000U	/* Physical SDRAM */
+#define BCMA_SOC_PCI_MEM		0x08000000U	/* Host Mode sb2pcitranslation0 (64 MB) */
+#define BCMA_SOC_PCI_MEM_SZ		(64 * 1024 * 1024)
+#define BCMA_SOC_PCI_CFG		0x0c000000U	/* Host Mode sb2pcitranslation1 (64 MB) */
+#define BCMA_SOC_SDRAM_SWAPPED		0x10000000U	/* Byteswapped Physical SDRAM */
+#define BCMA_SOC_SDRAM_R2		0x80000000U	/* Region 2 for sdram (512 MB) */
+
+
+#define BCMA_SOC_PCI_DMA		0x40000000U	/* Client Mode sb2pcitranslation2 (1 GB) */
+#define BCMA_SOC_PCI_DMA2		0x80000000U	/* Client Mode sb2pcitranslation2 (1 GB) */
+#define BCMA_SOC_PCI_DMA_SZ		0x40000000U	/* Client Mode sb2pcitranslation2 size in bytes */
+#define BCMA_SOC_PCIE_DMA_L32		0x00000000U	/* PCIE Client Mode sb2pcitranslation2
+							 * (2 ZettaBytes), low 32 bits
+							 */
+#define BCMA_SOC_PCIE_DMA_H32		0x80000000U	/* PCIE Client Mode sb2pcitranslation2
+							 * (2 ZettaBytes), high 32 bits
+							 */
+
+#define BCMA_SOC_PCI1_MEM		0x40000000U	/* Host Mode sb2pcitranslation0 (64 MB) */
+#define BCMA_SOC_PCI1_CFG		0x44000000U	/* Host Mode sb2pcitranslation1 (64 MB) */
+#define BCMA_SOC_PCIE1_DMA_H32		0xc0000000U	/* PCIE Client Mode sb2pcitranslation2
+							 * (2 ZettaBytes), high 32 bits
+							 */
+
 #endif /* LINUX_BCMA_REGS_H_ */
diff --git a/include/linux/crashlog.h b/include/linux/crashlog.h
new file mode 100644
index 0000000..7a9ee61
--- /dev/null
+++ b/include/linux/crashlog.h
@@ -0,0 +1,17 @@
+#ifndef __CRASHLOG_H
+#define __CRASHLOG_H
+
+#ifdef CONFIG_CRASHLOG
+void crashlog_init_bootmem(struct bootmem_data *bdata);
+void crashlog_init_memblock(phys_addr_t addr, phys_addr_t size);
+#else
+static inline void crashlog_init_bootmem(struct bootmem_data *bdata)
+{
+}
+
+static inline void crashlog_init_memblock(phys_addr_t addr, phys_addr_t size)
+{
+}
+#endif
+
+#endif
diff --git a/include/linux/decompress/unlzo_mm.h b/include/linux/decompress/unlzo_mm.h
new file mode 100644
index 0000000..08f9e70
--- /dev/null
+++ b/include/linux/decompress/unlzo_mm.h
@@ -0,0 +1,10 @@
+#ifndef UNLZO_MM_H
+#define UNLZO_MM_H
+
+#ifdef STATIC
+#define INIT
+#else
+#define INIT __init
+#endif
+
+#endif
diff --git a/include/linux/export.h b/include/linux/export.h
index 696c0f4..a2d8a34 100644
--- a/include/linux/export.h
+++ b/include/linux/export.h
@@ -45,12 +45,19 @@
 #define __CRC_SYMBOL(sym, sec)
 #endif
 
+#ifdef MODULE
+#define __EXPORT_SUFFIX(sym)
+#else
+#define __EXPORT_SUFFIX(sym) "+" #sym
+#endif
+
 /* For every exported symbol, place a struct in the __ksymtab section */
 #define __EXPORT_SYMBOL(sym, sec)				\
 	extern typeof(sym) sym;					\
 	__CRC_SYMBOL(sym, sec)					\
 	static const char __kstrtab_##sym[]			\
-	__attribute__((section("__ksymtab_strings"), aligned(1))) \
+	__attribute__((section("__ksymtab_strings"		\
+	  __EXPORT_SUFFIX(sym)), aligned(1)))			\
 	= MODULE_SYMBOL_PREFIX #sym;				\
 	static const struct kernel_symbol __ksymtab_##sym	\
 	__used							\
diff --git a/include/linux/fb.h b/include/linux/fb.h
index a395b8c..50e91ff 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -127,6 +127,7 @@
 #define FB_ACCEL_TRIDENT_BLADE3D 52	/* Trident Blade3D		*/
 #define FB_ACCEL_TRIDENT_BLADEXP 53	/* Trident BladeXP		*/
 #define FB_ACCEL_CIRRUS_ALPINE   53	/* Cirrus Logic 543x/544x/5480	*/
+#define FB_ACCEL_GLAMO		50	/* SMedia Glamo                 */
 #define FB_ACCEL_NEOMAGIC_NM2070 90	/* NeoMagic NM2070              */
 #define FB_ACCEL_NEOMAGIC_NM2090 91	/* NeoMagic NM2090              */
 #define FB_ACCEL_NEOMAGIC_NM2093 92	/* NeoMagic NM2093              */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index fd65e0d..d2a201e 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -484,6 +484,12 @@
  */
 #include <linux/quota.h>
 
+/*
+ * Maximum number of layers of fs stack.  Needs to be limited to
+ * prevent kernel stack overflow
+ */
+#define FILESYSTEM_MAX_STACK_DEPTH 2
+
 /** 
  * enum positive_aop_returns - aop return codes with specific semantics
  *
@@ -1501,6 +1507,11 @@
 
 	/* Being remounted read-only */
 	int s_readonly_remount;
+
+	/*
+	 * Indicates how deep in a filesystem stack this SB is
+	 */
+	int s_stack_depth;
 };
 
 /* superblock cache pruning functions */
@@ -1658,6 +1669,8 @@
 	void (*truncate_range)(struct inode *, loff_t, loff_t);
 	int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start,
 		      u64 len);
+	struct file *(*open) (struct dentry *, struct file *,
+			      const struct cred *);
 } ____cacheline_aligned;
 
 struct seq_file;
@@ -2028,6 +2041,7 @@
 extern struct file *filp_open(const char *, int, umode_t);
 extern struct file *file_open_root(struct dentry *, struct vfsmount *,
 				   const char *, int);
+extern struct file *vfs_open(struct path *, struct file *, const struct cred *);
 extern struct file * dentry_open(struct dentry *, struct vfsmount *, int,
 				 const struct cred *);
 extern int filp_close(struct file *, fl_owner_t id);
diff --git a/include/linux/gpio.h b/include/linux/gpio.h
index 38ac48b..38afe24 100644
--- a/include/linux/gpio.h
+++ b/include/linux/gpio.h
@@ -14,6 +14,11 @@
 #define GPIOF_OUT_INIT_LOW	(GPIOF_DIR_OUT | GPIOF_INIT_LOW)
 #define GPIOF_OUT_INIT_HIGH	(GPIOF_DIR_OUT | GPIOF_INIT_HIGH)
 
+#define GPIOF_EXPORT		(1 << 2)
+#define GPIOF_EXPORT_CHANGEABLE	(1 << 3)
+#define GPIOF_EXPORT_DIR_FIXED	(GPIOF_EXPORT)
+#define GPIOF_EXPORT_DIR_CHANGEABLE (GPIOF_EXPORT | GPIOF_EXPORT_CHANGEABLE)
+
 /**
  * struct gpio - a structure describing a GPIO with configuration
  * @gpio:	the GPIO number
diff --git a/include/linux/if.h b/include/linux/if.h
index 06b6ef6..cffa754 100644
--- a/include/linux/if.h
+++ b/include/linux/if.h
@@ -80,6 +80,7 @@
 					 * skbs on transmit */
 #define IFF_UNICAST_FLT	0x20000		/* Supports unicast filtering	*/
 #define IFF_TEAM_PORT	0x40000		/* device used as team port */
+#define IFF_NO_IP_ALIGN	0x80000		/* do not ip-align allocated rx pkts */
 
 #define IF_GET_IFACE	0x0001		/* for querying only */
 #define IF_GET_PROTO	0x0002
diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h
index dd3f201..0d8ba92 100644
--- a/include/linux/if_bridge.h
+++ b/include/linux/if_bridge.h
@@ -102,10 +102,24 @@
 #include <linux/netdevice.h>
 
 extern void brioctl_set(int (*ioctl_hook)(struct net *, unsigned int, void __user *));
+extern struct net_device *br_port_dev_get(struct net_device *dev, unsigned char *addr);
+extern void br_refresh_fdb_entry(struct net_device *dev, const char *addr);
+extern void br_dev_update_stats(struct net_device *dev, struct rtnl_link_stats64 *nlstats);
 
 typedef int br_should_route_hook_t(struct sk_buff *skb);
 extern br_should_route_hook_t __rcu *br_should_route_hook;
 
+typedef struct net_bridge_port *br_get_dst_hook_t(const struct net_bridge_port *src,
+		struct sk_buff **skb);
+extern br_get_dst_hook_t __rcu *br_get_dst_hook;
+
+typedef int (br_multicast_handle_hook_t)(const struct net_bridge_port *src,
+		struct sk_buff *skb);
+extern br_multicast_handle_hook_t __rcu *br_multicast_handle_hook;
+
+typedef void (br_notify_hook_t)(int group, int event, const void *ptr);
+extern br_notify_hook_t __rcu *br_notify_hook;
+
 #endif
 
 #endif
diff --git a/include/linux/if_packet.h b/include/linux/if_packet.h
index f379929..e06b393 100644
--- a/include/linux/if_packet.h
+++ b/include/linux/if_packet.h
@@ -29,6 +29,8 @@
 /* These ones are invisible by user level */
 #define PACKET_LOOPBACK		5		/* MC/BRD frame looped back */
 #define PACKET_FASTROUTE	6		/* Fastrouted frame	*/
+#define PACKET_MASK_ANY		0xffffffff	/* mask for packet type bits */
+
 
 /* Packet socket options */
 
@@ -50,6 +52,7 @@
 #define PACKET_TX_TIMESTAMP		16
 #define PACKET_TIMESTAMP		17
 #define PACKET_FANOUT			18
+#define PACKET_RECV_TYPE		19
 
 #define PACKET_FANOUT_HASH		0
 #define PACKET_FANOUT_LB		1
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index a64b00e..d4bcadc 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -44,7 +44,6 @@
  *
  * IRQF_DISABLED - keep irqs disabled when calling the action handler.
  *                 DEPRECATED. This flag is a NOOP and scheduled to be removed
- * IRQF_SAMPLE_RANDOM - irq is used to feed the random generator
  * IRQF_SHARED - allow sharing the irq among several devices
  * IRQF_PROBE_SHARED - set by callers when they expect sharing mismatches to occur
  * IRQF_TIMER - Flag to mark this interrupt as timer interrupt
@@ -63,7 +62,6 @@
  *                resume time.
  */
 #define IRQF_DISABLED		0x00000020
-#define IRQF_SAMPLE_RANDOM	0x00000040
 #define IRQF_SHARED		0x00000080
 #define IRQF_PROBE_SHARED	0x00000100
 #define __IRQF_TIMER		0x00000200
diff --git a/include/linux/irqdesc.h b/include/linux/irqdesc.h
index f1e2527..9a323d1 100644
--- a/include/linux/irqdesc.h
+++ b/include/linux/irqdesc.h
@@ -39,7 +39,6 @@
  */
 struct irq_desc {
 	struct irq_data		irq_data;
-	struct timer_rand_state *timer_rand_state;
 	unsigned int __percpu	*kstat_irqs;
 	irq_flow_handler_t	handle_irq;
 #ifdef CONFIG_IRQ_PREFLOW_FASTEOI
diff --git a/include/linux/jffs2.h b/include/linux/jffs2.h
index a18b719..f3431a5 100644
--- a/include/linux/jffs2.h
+++ b/include/linux/jffs2.h
@@ -46,6 +46,7 @@
 #define JFFS2_COMPR_DYNRUBIN	0x05
 #define JFFS2_COMPR_ZLIB	0x06
 #define JFFS2_COMPR_LZO		0x07
+#define JFFS2_COMPR_LZMA	0x08
 /* Compatibility flags. */
 #define JFFS2_COMPAT_MASK 0xc000      /* What do to if an unknown nodetype is found */
 #define JFFS2_NODE_ACCURATE 0x2000
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index fc615a9..8fc66d3 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -31,6 +31,8 @@
 #define UEVENT_NUM_ENVP			32	/* number of env pointers */
 #define UEVENT_BUFFER_SIZE		2048	/* buffer for the variables */
 
+struct sk_buff;
+
 /* path to the userspace helper executed on an event */
 extern char uevent_helper[];
 
@@ -213,6 +215,10 @@
 
 int kobject_action_type(const char *buf, size_t count,
 			enum kobject_action *type);
+
+int broadcast_uevent(struct sk_buff *skb, __u32 pid, __u32 group,
+		     gfp_t allocation);
+
 #else
 static inline int kobject_uevent(struct kobject *kobj,
 				 enum kobject_action action)
@@ -229,6 +235,16 @@
 static inline int kobject_action_type(const char *buf, size_t count,
 				      enum kobject_action *type)
 { return -EINVAL; }
+
+void kfree_skb(struct sk_buff *);
+
+static inline int broadcast_uevent(struct sk_buff *skb, __u32 pid, __u32 group,
+				   gfp_t allocation)
+{
+	kfree_skb(skb);
+	return 0;
+}
+
 #endif
 
 #endif /* _KOBJECT_H_ */
diff --git a/include/linux/lzma.h b/include/linux/lzma.h
new file mode 100644
index 0000000..5f31334
--- /dev/null
+++ b/include/linux/lzma.h
@@ -0,0 +1,62 @@
+#ifndef __LZMA_H__
+#define __LZMA_H__
+
+#ifdef __KERNEL__
+	#include <linux/kernel.h>
+	#include <linux/sched.h>
+	#include <linux/slab.h>
+	#include <linux/vmalloc.h>
+	#include <linux/init.h>
+	#define LZMA_MALLOC vmalloc
+	#define LZMA_FREE vfree
+	#define PRINT_ERROR(msg) printk(KERN_WARNING #msg)
+	#define INIT __init
+	#define STATIC static
+#else
+	#include <stdint.h>
+	#include <stdlib.h>
+	#include <stdio.h>
+	#include <unistd.h>
+	#include <string.h>
+	#include <asm/types.h>
+	#include <errno.h>
+	#include <linux/jffs2.h>
+	#ifndef PAGE_SIZE
+		extern int page_size;
+		#define PAGE_SIZE page_size
+	#endif
+	#define LZMA_MALLOC malloc
+	#define LZMA_FREE free
+	#define PRINT_ERROR(msg) fprintf(stderr, msg)
+	#define INIT
+	#define STATIC
+#endif
+
+#include "lzma/LzmaDec.h"
+#include "lzma/LzmaEnc.h"
+
+#define LZMA_BEST_LEVEL (9)
+#define LZMA_BEST_LC    (0)
+#define LZMA_BEST_LP    (0)
+#define LZMA_BEST_PB    (0)
+#define LZMA_BEST_FB  (273)
+
+#define LZMA_BEST_DICT(n) (((int)((n) / 2)) * 2)
+
+static void *p_lzma_malloc(void *p, size_t size)
+{
+        if (size == 0)
+                return NULL;
+
+        return LZMA_MALLOC(size);
+}
+
+static void p_lzma_free(void *p, void *address)
+{
+        if (address != NULL)
+                LZMA_FREE(address);
+}
+
+static ISzAlloc lzma_alloc = {p_lzma_malloc, p_lzma_free};
+
+#endif
diff --git a/include/linux/lzma/LzFind.h b/include/linux/lzma/LzFind.h
new file mode 100644
index 0000000..6d4f8e2
--- /dev/null
+++ b/include/linux/lzma/LzFind.h
@@ -0,0 +1,98 @@
+/* LzFind.h -- Match finder for LZ algorithms
+2009-04-22 : Igor Pavlov : Public domain */
+
+#ifndef __LZ_FIND_H
+#define __LZ_FIND_H
+
+#include "Types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef UInt32 CLzRef;
+
+typedef struct _CMatchFinder
+{
+  Byte *buffer;
+  UInt32 pos;
+  UInt32 posLimit;
+  UInt32 streamPos;
+  UInt32 lenLimit;
+
+  UInt32 cyclicBufferPos;
+  UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */
+
+  UInt32 matchMaxLen;
+  CLzRef *hash;
+  CLzRef *son;
+  UInt32 hashMask;
+  UInt32 cutValue;
+
+  Byte *bufferBase;
+  ISeqInStream *stream;
+  int streamEndWasReached;
+
+  UInt32 blockSize;
+  UInt32 keepSizeBefore;
+  UInt32 keepSizeAfter;
+
+  UInt32 numHashBytes;
+  int directInput;
+  size_t directInputRem;
+  int btMode;
+  int bigHash;
+  UInt32 historySize;
+  UInt32 fixedHashSize;
+  UInt32 hashSizeSum;
+  UInt32 numSons;
+  SRes result;
+  UInt32 crc[256];
+} CMatchFinder;
+
+#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer)
+#define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)])
+
+#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos)
+
+void MatchFinder_Construct(CMatchFinder *p);
+
+/* Conditions:
+     historySize <= 3 GB
+     keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB
+*/
+int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
+    UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
+    ISzAlloc *alloc);
+void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc);
+
+/*
+Conditions:
+  Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func.
+  Mf_GetPointerToCurrentPos_Func's result must be used only before any other function
+*/
+
+typedef void (*Mf_Init_Func)(void *object);
+typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index);
+typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object);
+typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object);
+typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances);
+typedef void (*Mf_Skip_Func)(void *object, UInt32);
+
+typedef struct _IMatchFinder
+{
+  Mf_Init_Func Init;
+  Mf_GetIndexByte_Func GetIndexByte;
+  Mf_GetNumAvailableBytes_Func GetNumAvailableBytes;
+  Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos;
+  Mf_GetMatches_Func GetMatches;
+  Mf_Skip_Func Skip;
+} IMatchFinder;
+
+void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/linux/lzma/LzHash.h b/include/linux/lzma/LzHash.h
new file mode 100644
index 0000000..f3e8996
--- /dev/null
+++ b/include/linux/lzma/LzHash.h
@@ -0,0 +1,54 @@
+/* LzHash.h -- HASH functions for LZ algorithms
+2009-02-07 : Igor Pavlov : Public domain */
+
+#ifndef __LZ_HASH_H
+#define __LZ_HASH_H
+
+#define kHash2Size (1 << 10)
+#define kHash3Size (1 << 16)
+#define kHash4Size (1 << 20)
+
+#define kFix3HashSize (kHash2Size)
+#define kFix4HashSize (kHash2Size + kHash3Size)
+#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size)
+
+#define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8);
+
+#define HASH3_CALC { \
+  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
+  hash2Value = temp & (kHash2Size - 1); \
+  hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; }
+
+#define HASH4_CALC { \
+  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
+  hash2Value = temp & (kHash2Size - 1); \
+  hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
+  hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; }
+
+#define HASH5_CALC { \
+  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
+  hash2Value = temp & (kHash2Size - 1); \
+  hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
+  hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \
+  hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \
+  hash4Value &= (kHash4Size - 1); }
+
+/* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */
+#define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF;
+
+
+#define MT_HASH2_CALC \
+  hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1);
+
+#define MT_HASH3_CALC { \
+  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
+  hash2Value = temp & (kHash2Size - 1); \
+  hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); }
+
+#define MT_HASH4_CALC { \
+  UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
+  hash2Value = temp & (kHash2Size - 1); \
+  hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
+  hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); }
+
+#endif
diff --git a/include/linux/lzma/LzmaDec.h b/include/linux/lzma/LzmaDec.h
new file mode 100644
index 0000000..c90f95e
--- /dev/null
+++ b/include/linux/lzma/LzmaDec.h
@@ -0,0 +1,130 @@
+/* LzmaDec.h -- LZMA Decoder
+2009-02-07 : Igor Pavlov : Public domain */
+
+#ifndef __LZMA_DEC_H
+#define __LZMA_DEC_H
+
+#include "Types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* #define _LZMA_PROB32 */
+/* _LZMA_PROB32 can increase the speed on some CPUs,
+   but memory usage for CLzmaDec::probs will be doubled in that case */
+
+#ifdef _LZMA_PROB32
+#define CLzmaProb UInt32
+#else
+#define CLzmaProb UInt16
+#endif
+
+
+/* ---------- LZMA Properties ---------- */
+
+#define LZMA_PROPS_SIZE 5
+
+typedef struct _CLzmaProps
+{
+  unsigned lc, lp, pb;
+  UInt32 dicSize;
+} CLzmaProps;
+
+
+/* ---------- LZMA Decoder state ---------- */
+
+/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case.
+   Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */
+
+#define LZMA_REQUIRED_INPUT_MAX 20
+
+typedef struct
+{
+  CLzmaProps prop;
+  CLzmaProb *probs;
+  Byte *dic;
+  const Byte *buf;
+  UInt32 range, code;
+  SizeT dicPos;
+  SizeT dicBufSize;
+  UInt32 processedPos;
+  UInt32 checkDicSize;
+  unsigned state;
+  UInt32 reps[4];
+  unsigned remainLen;
+  int needFlush;
+  int needInitState;
+  UInt32 numProbs;
+  unsigned tempBufSize;
+  Byte tempBuf[LZMA_REQUIRED_INPUT_MAX];
+} CLzmaDec;
+
+#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; }
+
+/* There are two types of LZMA streams:
+     0) Stream with end mark. That end mark adds about 6 bytes to compressed size.
+     1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */
+
+typedef enum
+{
+  LZMA_FINISH_ANY,   /* finish at any point */
+  LZMA_FINISH_END    /* block must be finished at the end */
+} ELzmaFinishMode;
+
+/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!!
+
+   You must use LZMA_FINISH_END, when you know that current output buffer
+   covers last bytes of block. In other cases you must use LZMA_FINISH_ANY.
+
+   If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK,
+   and output value of destLen will be less than output buffer size limit.
+   You can check status result also.
+
+   You can use multiple checks to test data integrity after full decompression:
+     1) Check Result and "status" variable.
+     2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.
+     3) Check that output(srcLen) = compressedSize, if you know real compressedSize.
+        You must use correct finish mode in that case. */
+
+typedef enum
+{
+  LZMA_STATUS_NOT_SPECIFIED,               /* use main error code instead */
+  LZMA_STATUS_FINISHED_WITH_MARK,          /* stream was finished with end mark. */
+  LZMA_STATUS_NOT_FINISHED,                /* stream was not finished */
+  LZMA_STATUS_NEEDS_MORE_INPUT,            /* you must provide more input bytes */
+  LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK  /* there is probability that stream was finished without end mark */
+} ELzmaStatus;
+
+/* ELzmaStatus is used only as output value for function call */
+
+/* ---------- One Call Interface ---------- */
+
+/* LzmaDecode
+
+finishMode:
+  It has meaning only if the decoding reaches output limit (*destLen).
+  LZMA_FINISH_ANY - Decode just destLen bytes.
+  LZMA_FINISH_END - Stream must be finished after (*destLen).
+
+Returns:
+  SZ_OK
+    status:
+      LZMA_STATUS_FINISHED_WITH_MARK
+      LZMA_STATUS_NOT_FINISHED
+      LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
+  SZ_ERROR_DATA - Data error
+  SZ_ERROR_MEM  - Memory allocation error
+  SZ_ERROR_UNSUPPORTED - Unsupported properties
+  SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
+*/
+
+SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
+    const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
+    ELzmaStatus *status, ISzAlloc *alloc);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/linux/lzma/LzmaEnc.h b/include/linux/lzma/LzmaEnc.h
new file mode 100644
index 0000000..2986c04
--- /dev/null
+++ b/include/linux/lzma/LzmaEnc.h
@@ -0,0 +1,60 @@
+/*  LzmaEnc.h -- LZMA Encoder
+2009-02-07 : Igor Pavlov : Public domain */
+
+#ifndef __LZMA_ENC_H
+#define __LZMA_ENC_H
+
+#include "Types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LZMA_PROPS_SIZE 5
+
+typedef struct _CLzmaEncProps
+{
+  int level;       /*  0 <= level <= 9 */
+  UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version
+                      (1 << 12) <= dictSize <= (1 << 30) for 64-bit version
+                       default = (1 << 24) */
+  int lc;          /* 0 <= lc <= 8, default = 3 */
+  int lp;          /* 0 <= lp <= 4, default = 0 */
+  int pb;          /* 0 <= pb <= 4, default = 2 */
+  int algo;        /* 0 - fast, 1 - normal, default = 1 */
+  int fb;          /* 5 <= fb <= 273, default = 32 */
+  int btMode;      /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */
+  int numHashBytes; /* 2, 3 or 4, default = 4 */
+  UInt32 mc;        /* 1 <= mc <= (1 << 30), default = 32 */
+  unsigned writeEndMark;  /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */
+  int numThreads;  /* 1 or 2, default = 2 */
+} CLzmaEncProps;
+
+void LzmaEncProps_Init(CLzmaEncProps *p);
+
+/* ---------- CLzmaEncHandle Interface ---------- */
+
+/* LzmaEnc_* functions can return the following exit codes:
+Returns:
+  SZ_OK           - OK
+  SZ_ERROR_MEM    - Memory allocation error
+  SZ_ERROR_PARAM  - Incorrect paramater in props
+  SZ_ERROR_WRITE  - Write callback error.
+  SZ_ERROR_PROGRESS - some break from progress callback
+  SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
+*/
+
+typedef void * CLzmaEncHandle;
+
+CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc);
+void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig);
+SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props);
+SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size);
+SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
+    int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/linux/lzma/Types.h b/include/linux/lzma/Types.h
new file mode 100644
index 0000000..4751acd
--- /dev/null
+++ b/include/linux/lzma/Types.h
@@ -0,0 +1,226 @@
+/* Types.h -- Basic types
+2009-11-23 : Igor Pavlov : Public domain */
+
+#ifndef __7Z_TYPES_H
+#define __7Z_TYPES_H
+
+#include <stddef.h>
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#ifndef EXTERN_C_BEGIN
+#ifdef __cplusplus
+#define EXTERN_C_BEGIN extern "C" {
+#define EXTERN_C_END }
+#else
+#define EXTERN_C_BEGIN
+#define EXTERN_C_END
+#endif
+#endif
+
+EXTERN_C_BEGIN
+
+#define SZ_OK 0
+
+#define SZ_ERROR_DATA 1
+#define SZ_ERROR_MEM 2
+#define SZ_ERROR_CRC 3
+#define SZ_ERROR_UNSUPPORTED 4
+#define SZ_ERROR_PARAM 5
+#define SZ_ERROR_INPUT_EOF 6
+#define SZ_ERROR_OUTPUT_EOF 7
+#define SZ_ERROR_READ 8
+#define SZ_ERROR_WRITE 9
+#define SZ_ERROR_PROGRESS 10
+#define SZ_ERROR_FAIL 11
+#define SZ_ERROR_THREAD 12
+
+#define SZ_ERROR_ARCHIVE 16
+#define SZ_ERROR_NO_ARCHIVE 17
+
+typedef int SRes;
+
+#ifdef _WIN32
+typedef DWORD WRes;
+#else
+typedef int WRes;
+#endif
+
+#ifndef RINOK
+#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; }
+#endif
+
+typedef unsigned char Byte;
+typedef short Int16;
+typedef unsigned short UInt16;
+
+#ifdef _LZMA_UINT32_IS_ULONG
+typedef long Int32;
+typedef unsigned long UInt32;
+#else
+typedef int Int32;
+typedef unsigned int UInt32;
+#endif
+
+#ifdef _SZ_NO_INT_64
+
+/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers.
+   NOTES: Some code will work incorrectly in that case! */
+
+typedef long Int64;
+typedef unsigned long UInt64;
+
+#else
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+typedef __int64 Int64;
+typedef unsigned __int64 UInt64;
+#else
+typedef long long int Int64;
+typedef unsigned long long int UInt64;
+#endif
+
+#endif
+
+#ifdef _LZMA_NO_SYSTEM_SIZE_T
+typedef UInt32 SizeT;
+#else
+typedef size_t SizeT;
+#endif
+
+typedef int Bool;
+#define True 1
+#define False 0
+
+
+#ifdef _WIN32
+#define MY_STD_CALL __stdcall
+#else
+#define MY_STD_CALL
+#endif
+
+#ifdef _MSC_VER
+
+#if _MSC_VER >= 1300
+#define MY_NO_INLINE __declspec(noinline)
+#else
+#define MY_NO_INLINE
+#endif
+
+#define MY_CDECL __cdecl
+#define MY_FAST_CALL __fastcall
+
+#else
+
+#define MY_CDECL
+#define MY_FAST_CALL
+
+#endif
+
+
+/* The following interfaces use first parameter as pointer to structure */
+
+typedef struct
+{
+  SRes (*Read)(void *p, void *buf, size_t *size);
+    /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
+       (output(*size) < input(*size)) is allowed */
+} ISeqInStream;
+
+/* it can return SZ_ERROR_INPUT_EOF */
+SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size);
+SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType);
+SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf);
+
+typedef struct
+{
+  size_t (*Write)(void *p, const void *buf, size_t size);
+    /* Returns: result - the number of actually written bytes.
+       (result < size) means error */
+} ISeqOutStream;
+
+typedef enum
+{
+  SZ_SEEK_SET = 0,
+  SZ_SEEK_CUR = 1,
+  SZ_SEEK_END = 2
+} ESzSeek;
+
+typedef struct
+{
+  SRes (*Read)(void *p, void *buf, size_t *size);  /* same as ISeqInStream::Read */
+  SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
+} ISeekInStream;
+
+typedef struct
+{
+  SRes (*Look)(void *p, void **buf, size_t *size);
+    /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
+       (output(*size) > input(*size)) is not allowed
+       (output(*size) < input(*size)) is allowed */
+  SRes (*Skip)(void *p, size_t offset);
+    /* offset must be <= output(*size) of Look */
+
+  SRes (*Read)(void *p, void *buf, size_t *size);
+    /* reads directly (without buffer). It's same as ISeqInStream::Read */
+  SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
+} ILookInStream;
+
+SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size);
+SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset);
+
+/* reads via ILookInStream::Read */
+SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType);
+SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size);
+
+#define LookToRead_BUF_SIZE (1 << 14)
+
+typedef struct
+{
+  ILookInStream s;
+  ISeekInStream *realStream;
+  size_t pos;
+  size_t size;
+  Byte buf[LookToRead_BUF_SIZE];
+} CLookToRead;
+
+void LookToRead_CreateVTable(CLookToRead *p, int lookahead);
+void LookToRead_Init(CLookToRead *p);
+
+typedef struct
+{
+  ISeqInStream s;
+  ILookInStream *realStream;
+} CSecToLook;
+
+void SecToLook_CreateVTable(CSecToLook *p);
+
+typedef struct
+{
+  ISeqInStream s;
+  ILookInStream *realStream;
+} CSecToRead;
+
+void SecToRead_CreateVTable(CSecToRead *p);
+
+typedef struct
+{
+  SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize);
+    /* Returns: result. (result != SZ_OK) means break.
+       Value (UInt64)(Int64)-1 for size means unknown value. */
+} ICompressProgress;
+
+typedef struct
+{
+  void *(*Alloc)(void *p, size_t size);
+  void (*Free)(void *p, void *address); /* address can be 0 */
+} ISzAlloc;
+
+#define IAlloc_Alloc(p, size) (p)->Alloc((p), size)
+#define IAlloc_Free(p, a) (p)->Free((p), a)
+
+EXTERN_C_END
+
+#endif
diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h
index 0549d211..dd2eb69 100644
--- a/include/linux/miscdevice.h
+++ b/include/linux/miscdevice.h
@@ -19,6 +19,7 @@
 #define APOLLO_MOUSE_MINOR	7
 #define PC110PAD_MINOR		9
 /*#define ADB_MOUSE_MINOR	10	FIXME OBSOLETE */
+#define CRYPTODEV_MINOR		70	/* /dev/crypto */
 #define WATCHDOG_MINOR		130	/* Watchdog timer     */
 #define TEMP_MINOR		131	/* Temperature Sensor */
 #define RTC_MINOR		135
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 17b27cd..25b86db 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -872,6 +872,7 @@
 
 int shmem_lock(struct file *file, int lock, struct user_struct *user);
 struct file *shmem_file_setup(const char *name, loff_t size, unsigned long flags);
+void shmem_set_file(struct vm_area_struct *vma, struct file *file);
 int shmem_zero_setup(struct vm_area_struct *);
 
 extern int can_do_mlock(void);
diff --git a/include/linux/mmc/gpiommc.h b/include/linux/mmc/gpiommc.h
new file mode 100644
index 0000000..5c11b09
--- /dev/null
+++ b/include/linux/mmc/gpiommc.h
@@ -0,0 +1,71 @@
+/*
+ * Device driver for MMC/SD cards driven over a GPIO bus.
+ *
+ * Copyright (c) 2008 Michael Buesch
+ *
+ * Licensed under the GNU/GPL version 2.
+ */
+#ifndef LINUX_GPIOMMC_H_
+#define LINUX_GPIOMMC_H_
+
+#include <linux/types.h>
+
+
+#define GPIOMMC_MAX_NAMELEN		15
+#define GPIOMMC_MAX_NAMELEN_STR		__stringify(GPIOMMC_MAX_NAMELEN)
+
+/**
+ * struct gpiommc_pins - Hardware pin assignments
+ *
+ * @gpio_di: The GPIO number of the DATA IN pin
+ * @gpio_do: The GPIO number of the DATA OUT pin
+ * @gpio_clk: The GPIO number of the CLOCK pin
+ * @gpio_cs: The GPIO number of the CHIPSELECT pin
+ * @cs_activelow: If true, the chip is considered selected if @gpio_cs is low.
+ */
+struct gpiommc_pins {
+	unsigned int gpio_di;
+	unsigned int gpio_do;
+	unsigned int gpio_clk;
+	unsigned int gpio_cs;
+	bool cs_activelow;
+};
+
+/**
+ * struct gpiommc_platform_data - Platform data for a MMC-over-SPI-GPIO device.
+ *
+ * @name: The unique name string of the device.
+ * @pins: The hardware pin assignments.
+ * @mode: The hardware mode. This is either SPI_MODE_0,
+ *        SPI_MODE_1, SPI_MODE_2 or SPI_MODE_3. See the SPI documentation.
+ * @no_spi_delay: Do not use delays in the lowlevel SPI bitbanging code.
+ *                This is not standards compliant, but may be required for some
+ *                embedded machines to gain reasonable speed.
+ * @max_bus_speed: The maximum speed of the SPI bus, in Hertz.
+ */
+struct gpiommc_platform_data {
+	char name[GPIOMMC_MAX_NAMELEN + 1];
+	struct gpiommc_pins pins;
+	u8 mode;
+	bool no_spi_delay;
+	unsigned int max_bus_speed;
+};
+
+/**
+ * GPIOMMC_PLATDEV_NAME - The platform device name string.
+ *
+ * The name string that has to be used for platform_device_alloc
+ * when allocating a gpiommc device.
+ */
+#define GPIOMMC_PLATDEV_NAME	"gpiommc"
+
+/**
+ * gpiommc_next_id - Get another platform device ID number.
+ *
+ * This returns the next platform device ID number that has to be used
+ * for platform_device_alloc. The ID is opaque and should not be used for
+ * anything else.
+ */
+int gpiommc_next_id(void);
+
+#endif /* LINUX_GPIOMMC_H_ */
diff --git a/include/linux/mount.h b/include/linux/mount.h
index d7029f4..344a262 100644
--- a/include/linux/mount.h
+++ b/include/linux/mount.h
@@ -66,6 +66,9 @@
 extern void mnt_unpin(struct vfsmount *mnt);
 extern int __mnt_is_readonly(struct vfsmount *mnt);
 
+struct path;
+extern struct vfsmount *clone_private_mount(struct path *path);
+
 struct file_system_type;
 extern struct vfsmount *vfs_kern_mount(struct file_system_type *type,
 				      int flags, const char *name,
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index d43dc25..e2f4ca3 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -58,6 +58,10 @@
 	u_long priv;
 	u_char state;
 	struct erase_info *next;
+
+	u8 *erase_buf;
+	u32 erase_buf_ofs;
+	bool partial_start;
 };
 
 struct mtd_erase_region_info {
@@ -114,6 +118,7 @@
 
 struct module;	/* only needed for owner field in mtd_info */
 
+struct mtd_info;
 struct mtd_info {
 	u_char type;
 	uint32_t flags;
@@ -214,6 +219,9 @@
 	int (*block_markbad) (struct mtd_info *mtd, loff_t ofs);
 	int (*suspend) (struct mtd_info *mtd);
 	void (*resume) (struct mtd_info *mtd);
+	int (*refresh_device)(struct mtd_info *mtd);
+	struct mtd_info *split;
+
 	/*
 	 * If the driver is something smart, like UBI, it may need to maintain
 	 * its own reference counting. The below functions are only for driver.
@@ -502,6 +510,7 @@
 			      int defnr_parts);
 #define mtd_device_register(master, parts, nr_parts)	\
 	mtd_device_parse_register(master, NULL, NULL, parts, nr_parts)
+extern int mtd_device_refresh(struct mtd_info *master);
 extern int mtd_device_unregister(struct mtd_info *master);
 extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num);
 extern int __get_mtd_device(struct mtd_info *mtd);
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 63b5a8b..c2761fd 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -622,6 +622,7 @@
 	unsigned int options;
 	unsigned int bbt_options;
 	const char **part_probe_types;
+	int (*chip_fixup)(struct mtd_info *mtd);
 };
 
 /* Keep gcc happy */
diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h
index 2475228..8b2fecc 100644
--- a/include/linux/mtd/partitions.h
+++ b/include/linux/mtd/partitions.h
@@ -35,13 +35,16 @@
  * Note: writeable partitions require their size and offset be
  * erasesize aligned (e.g. use MTDPART_OFS_NEXTBLK).
  */
+struct mtd_info;
 
+struct mtd_partition;
 struct mtd_partition {
 	char *name;			/* identifier string */
 	uint64_t size;			/* partition size */
 	uint64_t offset;		/* offset within the master MTD space */
 	uint32_t mask_flags;		/* master MTD flags to mask out for this partition */
 	struct nand_ecclayout *ecclayout;	/* out of band layout for this partition (NAND only) */
+	int (*refresh_partition)(struct mtd_info *);
 };
 
 #define MTDPART_OFS_RETAIN	(-3)
@@ -50,7 +53,6 @@
 #define MTDPART_SIZ_FULL	(0)
 
 
-struct mtd_info;
 struct device_node;
 
 /**
diff --git a/include/linux/mtd/physmap.h b/include/linux/mtd/physmap.h
index d2887e7..3eb3143 100644
--- a/include/linux/mtd/physmap.h
+++ b/include/linux/mtd/physmap.h
@@ -17,6 +17,7 @@
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
+#include <linux/platform_device.h>
 
 struct map_info;
 struct platform_device;
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 7e472b7..d8881b4 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -145,7 +145,7 @@
  */
 
 #if defined(CONFIG_WLAN) || IS_ENABLED(CONFIG_AX25)
-# if defined(CONFIG_MAC80211_MESH)
+# if 1 || defined(CONFIG_MAC80211_MESH)
 #  define LL_MAX_HEADER 128
 # else
 #  define LL_MAX_HEADER 96
@@ -1078,6 +1078,11 @@
 	const struct net_device_ops *netdev_ops;
 	const struct ethtool_ops *ethtool_ops;
 
+#ifdef CONFIG_ETHERNET_PACKET_MANGLE
+	void (*eth_mangle_rx)(struct net_device *dev, struct sk_buff *skb);
+	struct sk_buff *(*eth_mangle_tx)(struct net_device *dev, struct sk_buff *skb);
+#endif
+
 	/* Hardware header description */
 	const struct header_ops *header_ops;
 
@@ -1134,6 +1139,9 @@
 	void			*ax25_ptr;	/* AX.25 specific data */
 	struct wireless_dev	*ieee80211_ptr;	/* IEEE 802.11 specific data,
 						   assign before registering */
+#ifdef CONFIG_ETHERNET_PACKET_MANGLE
+	void			*phy_ptr; /* PHY device specific data */
+#endif
 
 /*
  * Cache lines mostly used on receive path (including eth_type_trans())
diff --git a/include/linux/netfilter/Kbuild b/include/linux/netfilter/Kbuild
index e144f54..57a04e5 100644
--- a/include/linux/netfilter/Kbuild
+++ b/include/linux/netfilter/Kbuild
@@ -49,6 +49,7 @@
 header-y += xt_helper.h
 header-y += xt_iprange.h
 header-y += xt_ipvs.h
+header-y += xt_layer7.h
 header-y += xt_length.h
 header-y += xt_limit.h
 header-y += xt_mac.h
diff --git a/include/linux/netfilter/nf_conntrack_sip.h b/include/linux/netfilter/nf_conntrack_sip.h
index 0ce91d5..feda699 100644
--- a/include/linux/netfilter/nf_conntrack_sip.h
+++ b/include/linux/netfilter/nf_conntrack_sip.h
@@ -2,12 +2,15 @@
 #define __NF_CONNTRACK_SIP_H__
 #ifdef __KERNEL__
 
+#include <linux/types.h>
+
 #define SIP_PORT	5060
 #define SIP_TIMEOUT	3600
 
 struct nf_ct_sip_master {
 	unsigned int	register_cseq;
 	unsigned int	invite_cseq;
+	__be16		forced_dport;
 };
 
 enum sip_expectation_classes {
diff --git a/include/linux/netfilter/xt_layer7.h b/include/linux/netfilter/xt_layer7.h
new file mode 100644
index 0000000..c38d3c4
--- /dev/null
+++ b/include/linux/netfilter/xt_layer7.h
@@ -0,0 +1,14 @@
+#ifndef _XT_LAYER7_H
+#define _XT_LAYER7_H
+
+#define MAX_PATTERN_LEN 8192
+#define MAX_PROTOCOL_LEN 256
+
+struct xt_layer7_info {
+    char protocol[MAX_PROTOCOL_LEN];
+    char pattern[MAX_PATTERN_LEN];
+    u_int8_t invert;
+    u_int8_t pkt;
+};
+
+#endif /* _XT_LAYER7_H */
diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h
index db79231..061bb34 100644
--- a/include/linux/netfilter_ipv4/ip_tables.h
+++ b/include/linux/netfilter_ipv4/ip_tables.h
@@ -93,6 +93,7 @@
 #define IPT_F_FRAG		0x01	/* Set if rule is a fragment rule */
 #define IPT_F_GOTO		0x02	/* Set if jump is a goto */
 #define IPT_F_MASK		0x03	/* All possible flag bits mask. */
+#define IPT_F_NO_DEF_MATCH	0x80	/* Internal: no default match rules present */
 
 /* Values for "inv" field in struct ipt_ip. */
 #define IPT_INV_VIA_IN		0x01	/* Invert the sense of IN IFACE. */
diff --git a/include/linux/phy.h b/include/linux/phy.h
index c599f7ec..4c76383 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -393,9 +393,18 @@
 	 */
 	int (*config_aneg)(struct phy_device *phydev);
 
+	/* Determine if autonegotiation is done */
+	int (*aneg_done)(struct phy_device *phydev);
+
 	/* Determines the negotiated speed and duplex */
 	int (*read_status)(struct phy_device *phydev);
 
+	/* 
+	 * Update the value in phydev->link to reflect the 
+	 * current link value
+	 */
+	int (*update_link)(struct phy_device *phydev);
+
 	/* Clears any pending interrupts */
 	int (*ack_interrupt)(struct phy_device *phydev);
 
@@ -515,6 +524,7 @@
 void phy_stop_machine(struct phy_device *phydev);
 int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd);
 int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd);
+int phy_ethtool_ioctl(struct phy_device *phydev, void *useraddr);
 int phy_mii_ioctl(struct phy_device *phydev,
 		struct ifreq *ifr, int cmd);
 int phy_start_interrupts(struct phy_device *phydev);
@@ -533,4 +543,22 @@
 void mdio_bus_exit(void);
 
 extern struct bus_type mdio_bus_type;
+
+struct mdio_board_info {
+	const char	*bus_id;
+	int		phy_addr;
+
+	const void	*platform_data;
+};
+
+#ifdef CONFIG_MDIO_BOARDINFO
+int mdiobus_register_board_info(const struct mdio_board_info *info, unsigned n);
+#else
+static inline int
+mdiobus_register_board_info(const struct mdio_board_info *info, unsigned n)
+{
+	return 0;
+}
+#endif
+
 #endif /* __PHY_H */
diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h
index 0d5b793..b0b0e40 100644
--- a/include/linux/pkt_sched.h
+++ b/include/linux/pkt_sched.h
@@ -193,6 +193,33 @@
 	__s32		allot;
 };
 
+/* ESFQ section */
+
+enum
+{
+        /* traditional */
+	TCA_SFQ_HASH_CLASSIC,
+	TCA_SFQ_HASH_DST,
+	TCA_SFQ_HASH_SRC,
+	TCA_SFQ_HASH_FWMARK,
+	/* conntrack */
+	TCA_SFQ_HASH_CTORIGDST,
+	TCA_SFQ_HASH_CTORIGSRC,
+	TCA_SFQ_HASH_CTREPLDST,
+	TCA_SFQ_HASH_CTREPLSRC,
+	TCA_SFQ_HASH_CTNATCHG,
+};
+
+struct tc_esfq_qopt
+{
+	unsigned	quantum;	/* Bytes per round allocated to flow */
+	int		perturb_period;	/* Period of hash perturbation */
+	__u32		limit;		/* Maximal packets in queue */
+	unsigned	divisor;	/* Hash divisor  */
+	unsigned	flows;		/* Maximal number of flows  */
+	unsigned	hash_kind;	/* Hash function to use for flow identification */
+};
+
 /* RED section */
 
 enum {
@@ -633,4 +660,84 @@
 	__u32 lmax;
 };
 
+/* CODEL */
+
+enum {
+	TCA_CODEL_UNSPEC,
+	TCA_CODEL_TARGET,
+	TCA_CODEL_LIMIT,
+	TCA_CODEL_INTERVAL,
+	TCA_CODEL_ECN,
+	__TCA_CODEL_MAX
+};
+
+#define TCA_CODEL_MAX	(__TCA_CODEL_MAX - 1)
+
+struct tc_codel_xstats {
+	__u32	maxpacket; /* largest packet we've seen so far */
+	__u32	count;	   /* how many drops we've done since the last time we
+			    * entered dropping state
+			    */
+	__u32	lastcount; /* count at entry to dropping state */
+	__u32	ldelay;    /* in-queue delay seen by most recently dequeued packet */
+	__s32	drop_next; /* time to drop next packet */
+	__u32	drop_overlimit; /* number of time max qdisc packet limit was hit */
+	__u32	ecn_mark;  /* number of packets we ECN marked instead of dropped */
+	__u32	dropping;  /* are we in dropping state ? */
+};
+
+/* FQ_CODEL */
+
+enum {
+	TCA_FQ_CODEL_UNSPEC,
+	TCA_FQ_CODEL_TARGET,
+	TCA_FQ_CODEL_LIMIT,
+	TCA_FQ_CODEL_INTERVAL,
+	TCA_FQ_CODEL_ECN,
+	TCA_FQ_CODEL_FLOWS,
+	TCA_FQ_CODEL_QUANTUM,
+	__TCA_FQ_CODEL_MAX
+};
+
+#define TCA_FQ_CODEL_MAX	(__TCA_FQ_CODEL_MAX - 1)
+
+enum {
+	TCA_FQ_CODEL_XSTATS_QDISC,
+	TCA_FQ_CODEL_XSTATS_CLASS,
+};
+
+struct tc_fq_codel_qd_stats {
+	__u32	maxpacket;	/* largest packet we've seen so far */
+	__u32	drop_overlimit; /* number of time max qdisc
+				 * packet limit was hit
+				 */
+	__u32	ecn_mark;	/* number of packets we ECN marked
+				 * instead of being dropped
+				 */
+	__u32	new_flow_count; /* number of time packets
+				 * created a 'new flow'
+				 */
+	__u32	new_flows_len;	/* count of flows in new list */
+	__u32	old_flows_len;	/* count of flows in old list */
+};
+
+struct tc_fq_codel_cl_stats {
+	__s32	deficit;
+	__u32	ldelay;		/* in-queue delay seen by most recently
+				 * dequeued packet
+				 */
+	__u32	count;
+	__u32	lastcount;
+	__u32	dropping;
+	__s32	drop_next;
+};
+
+struct tc_fq_codel_xstats {
+	__u32	type;
+	union {
+		struct tc_fq_codel_qd_stats qdisc_stats;
+		struct tc_fq_codel_cl_stats class_stats;
+	};
+};
+
 #endif
diff --git a/include/linux/random.h b/include/linux/random.h
index 8f74538..03f8e76 100644
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -34,6 +34,30 @@
 /* Clear the entropy pool and associated counters.  (Superuser only.) */
 #define RNDCLEARPOOL	_IO( 'R', 0x06 )
 
+#ifdef CONFIG_FIPS_RNG
+
+/* Size of seed value - equal to AES blocksize */
+#define AES_BLOCK_SIZE_BYTES	16
+#define SEED_SIZE_BYTES			AES_BLOCK_SIZE_BYTES
+/* Size of AES key */
+#define KEY_SIZE_BYTES		16
+
+/* ioctl() structure used by FIPS 140-2 Tests */
+struct rand_fips_test {
+	unsigned char key[KEY_SIZE_BYTES];			/* Input */
+	unsigned char datetime[SEED_SIZE_BYTES];	/* Input */
+	unsigned char seed[SEED_SIZE_BYTES];		/* Input */
+	unsigned char result[SEED_SIZE_BYTES];		/* Output */
+};
+
+/* FIPS 140-2 RNG Variable Seed Test. (Superuser only.) */
+#define RNDFIPSVST	_IOWR('R', 0x10, struct rand_fips_test)
+
+/* FIPS 140-2 RNG Monte Carlo Test. (Superuser only.) */
+#define RNDFIPSMCT	_IOWR('R', 0x11, struct rand_fips_test)
+
+#endif /* #ifdef CONFIG_FIPS_RNG */
+
 struct rand_pool_info {
 	int	entropy_count;
 	int	buf_size;
@@ -48,13 +72,17 @@
 
 #ifdef __KERNEL__
 
-extern void rand_initialize_irq(int irq);
-
+extern void add_device_randomness(const void *, unsigned int);
 extern void add_input_randomness(unsigned int type, unsigned int code,
 				 unsigned int value);
-extern void add_interrupt_randomness(int irq);
+extern void add_interrupt_randomness(int irq, int irq_flags);
+
+extern void random_input_words(__u32 *buf, size_t wordcount, int ent_count);
+extern int random_input_wait(void);
+#define HAS_RANDOM_INPUT_WAIT 1
 
 extern void get_random_bytes(void *buf, int nbytes);
+extern void get_random_bytes_arch(void *buf, int nbytes);
 void generate_random_uuid(unsigned char uuid_out[16]);
 
 #ifndef MODULE
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 42854ce..4f247e2 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -456,7 +456,8 @@
 	__u8			l4_rxhash:1;
 	__u8			wifi_acked_valid:1;
 	__u8			wifi_acked:1;
-	/* 10/12 bit hole (depending on ndisc_nodetype presence) */
+	__u8			fast_forwarded:1;
+	/* 9/11 bit hole (depending on ndisc_nodetype presence) */
 	kmemcheck_bitfield_end(flags2);
 
 #ifdef CONFIG_NET_DMA
@@ -1558,7 +1559,7 @@
  * NET_IP_ALIGN(2) + ethernet_header(14) + IP_header(20/40) + ports(8)
  */
 #ifndef NET_SKB_PAD
-#define NET_SKB_PAD	max(32, L1_CACHE_BYTES)
+#define NET_SKB_PAD	max(48, L1_CACHE_BYTES)
 #endif
 
 extern int ___pskb_trim(struct sk_buff *skb, unsigned int len);
@@ -1661,6 +1662,10 @@
 extern struct sk_buff *__netdev_alloc_skb(struct net_device *dev,
 		unsigned int length, gfp_t gfp_mask);
 
+extern struct sk_buff *__netdev_alloc_skb_ip_align(struct net_device *dev,
+		unsigned int length, gfp_t gfp);
+
+
 /**
  *	netdev_alloc_skb - allocate an skbuff for rx on a specific device
  *	@dev: network device to receive on
@@ -1680,16 +1685,6 @@
 	return __netdev_alloc_skb(dev, length, GFP_ATOMIC);
 }
 
-static inline struct sk_buff *__netdev_alloc_skb_ip_align(struct net_device *dev,
-		unsigned int length, gfp_t gfp)
-{
-	struct sk_buff *skb = __netdev_alloc_skb(dev, length + NET_IP_ALIGN, gfp);
-
-	if (NET_IP_ALIGN && skb)
-		skb_reserve(skb, NET_IP_ALIGN);
-	return skb;
-}
-
 static inline struct sk_buff *netdev_alloc_skb_ip_align(struct net_device *dev,
 		unsigned int length)
 {
@@ -1850,12 +1845,15 @@
 static inline int __skb_cow(struct sk_buff *skb, unsigned int headroom,
 			    int cloned)
 {
+	unsigned int alloc_headroom = headroom;
 	int delta = 0;
 
 	if (headroom < NET_SKB_PAD)
-		headroom = NET_SKB_PAD;
-	if (headroom > skb_headroom(skb))
-		delta = headroom - skb_headroom(skb);
+		alloc_headroom = NET_SKB_PAD;
+	if (headroom > skb_headroom(skb) ||
+	    (cloned && alloc_headroom > skb_headroom(skb))) {
+		delta = alloc_headroom - skb_headroom(skb);
+	}
 
 	if (delta || cloned)
 		return pskb_expand_head(skb, ALIGN(delta, NET_SKB_PAD), 0,
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 573c809..d22208f 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -127,8 +127,8 @@
  * to do various tricks to work around compiler limitations in order to
  * ensure proper constant folding.
  */
-#define KMALLOC_SHIFT_HIGH	((MAX_ORDER + PAGE_SHIFT - 1) <= 25 ? \
-				(MAX_ORDER + PAGE_SHIFT - 1) : 25)
+#define KMALLOC_SHIFT_HIGH	((MAX_ORDER + PAGE_SHIFT - 1) <= 17 ? \
+				(MAX_ORDER + PAGE_SHIFT - 1) : 17)
 
 #define KMALLOC_MAX_SIZE	(1UL << KMALLOC_SHIFT_HIGH)
 #define KMALLOC_MAX_ORDER	(KMALLOC_SHIFT_HIGH - PAGE_SHIFT)
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index 176fce9..f9e30a5 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -22,6 +22,7 @@
 #include <linux/device.h>
 #include <linux/mod_devicetable.h>
 #include <linux/slab.h>
+#include <linux/kthread.h>
 
 /*
  * INTERFACES between SPI master-side drivers and SPI infrastructure.
@@ -235,6 +236,27 @@
  *	the device whose settings are being modified.
  * @transfer: adds a message to the controller's transfer queue.
  * @cleanup: frees controller-specific state
+ * @queued: whether this master is providing an internal message queue
+ * @kworker: thread struct for message pump
+ * @kworker_task: pointer to task for message pump kworker thread
+ * @pump_messages: work struct for scheduling work to the message pump
+ * @queue_lock: spinlock to syncronise access to message queue
+ * @queue: message queue
+ * @cur_msg: the currently in-flight message
+ * @busy: message pump is busy
+ * @running: message pump is running
+ * @rt: whether this queue is set to run as a realtime task
+ * @prepare_transfer_hardware: a message will soon arrive from the queue
+ *	so the subsystem requests the driver to prepare the transfer hardware
+ *	by issuing this call
+ * @transfer_one_message: the subsystem calls the driver to transfer a single
+ *	message while queuing transfers that arrive in the meantime. When the
+ *	driver is finished with this message, it must call
+ *	spi_finalize_current_message() so the subsystem can issue the next
+ *	transfer
+ * @prepare_transfer_hardware: there are currently no more messages on the
+ *	queue so the subsystem notifies the driver that it may relax the
+ *	hardware by issuing this call
  *
  * Each SPI master controller can communicate with one or more @spi_device
  * children.  These make a small bus, sharing MOSI, MISO and SCK signals
@@ -318,6 +340,28 @@
 
 	/* called on release() to free memory provided by spi_master */
 	void			(*cleanup)(struct spi_device *spi);
+
+	/*
+	 * These hooks are for drivers that want to use the generic
+	 * master transfer queueing mechanism. If these are used, the
+	 * transfer() function above must NOT be specified by the driver.
+	 * Over time we expect SPI drivers to be phased over to this API.
+	 */
+	bool				queued;
+	struct kthread_worker		kworker;
+	struct task_struct		*kworker_task;
+	struct kthread_work		pump_messages;
+	spinlock_t			queue_lock;
+	struct list_head		queue;
+	struct spi_message		*cur_msg;
+	bool				busy;
+	bool				running;
+	bool				rt;
+
+	int (*prepare_transfer_hardware)(struct spi_master *master);
+	int (*transfer_one_message)(struct spi_master *master,
+				    struct spi_message *mesg);
+	int (*unprepare_transfer_hardware)(struct spi_master *master);
 };
 
 static inline void *spi_master_get_devdata(struct spi_master *master)
@@ -343,6 +387,13 @@
 		put_device(&master->dev);
 }
 
+/* PM calls that need to be issued by the driver */
+extern int spi_master_suspend(struct spi_master *master);
+extern int spi_master_resume(struct spi_master *master);
+
+/* Calls the driver make to interact with the message queue */
+extern struct spi_message *spi_get_next_queued_message(struct spi_master *master);
+extern void spi_finalize_current_message(struct spi_master *master);
 
 /* the spi driver core manages memory for the spi_master classdev */
 extern struct spi_master *
diff --git a/include/linux/spi/spi_gpio_old.h b/include/linux/spi/spi_gpio_old.h
new file mode 100644
index 0000000..5fc2cd6
--- /dev/null
+++ b/include/linux/spi/spi_gpio_old.h
@@ -0,0 +1,73 @@
+/*
+ * spi_gpio interface to platform code
+ *
+ * Copyright (c) 2008 Piotr Skamruk
+ * Copyright (c) 2008 Michael Buesch
+ *
+ * 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_SPI_SPI_GPIO
+#define _LINUX_SPI_SPI_GPIO
+
+#include <linux/types.h>
+#include <linux/spi/spi.h>
+
+
+/**
+ * struct spi_gpio_platform_data - Data definitions for a SPI-GPIO device.
+ *
+ * This structure holds information about a GPIO-based SPI device.
+ *
+ * @pin_clk: The GPIO pin number of the CLOCK pin.
+ *
+ * @pin_miso: The GPIO pin number of the MISO pin.
+ *
+ * @pin_mosi: The GPIO pin number of the MOSI pin.
+ *
+ * @pin_cs: The GPIO pin number of the CHIPSELECT pin.
+ *
+ * @cs_activelow: If true, the chip is selected when the CS line is low.
+ *
+ * @no_spi_delay: If true, no delay is done in the lowlevel bitbanging.
+ *                Note that doing no delay is not standards compliant,
+ *                but it might be needed to speed up transfers on some
+ *                slow embedded machines.
+ *
+ * @boardinfo_setup: This callback is called after the
+ *                   SPI master device was registered, but before the
+ *                   device is registered.
+ * @boardinfo_setup_data: Data argument passed to boardinfo_setup().
+ */
+struct spi_gpio_platform_data {
+	unsigned int pin_clk;
+	unsigned int pin_miso;
+	unsigned int pin_mosi;
+	unsigned int pin_cs;
+	bool cs_activelow;
+	bool no_spi_delay;
+	int (*boardinfo_setup)(struct spi_board_info *bi,
+			       struct spi_master *master,
+			       void *data);
+	void *boardinfo_setup_data;
+};
+
+/**
+ * SPI_GPIO_PLATDEV_NAME - The platform device name string.
+ *
+ * The name string that has to be used for platform_device_alloc
+ * when allocating a spi-gpio device.
+ */
+#define SPI_GPIO_PLATDEV_NAME	"spi-gpio"
+
+/**
+ * spi_gpio_next_id - Get another platform device ID number.
+ *
+ * This returns the next platform device ID number that has to be used
+ * for platform_device_alloc. The ID is opaque and should not be used for
+ * anything else.
+ */
+int spi_gpio_next_id(void);
+
+#endif /* _LINUX_SPI_SPI_GPIO */
diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h
index dcf35b0..bb674c0 100644
--- a/include/linux/ssb/ssb.h
+++ b/include/linux/ssb/ssb.h
@@ -16,6 +16,12 @@
 struct ssb_bus;
 struct ssb_driver;
 
+struct ssb_sprom_core_pwr_info {
+	u8 itssi_2g, itssi_5g;
+	u8 maxpwr_2g, maxpwr_5gl, maxpwr_5g, maxpwr_5gh;
+	u16 pa_2g[4], pa_5gl[4], pa_5g[4], pa_5gh[4];
+};
+
 struct ssb_sprom {
 	u8 revision;
 	u8 il0mac[6];		/* MAC address for 802.11b/g */
@@ -26,9 +32,12 @@
 	u8 et0mdcport;		/* MDIO for enet0 */
 	u8 et1mdcport;		/* MDIO for enet1 */
 	u16 board_rev;		/* Board revision number from SPROM. */
+	u16 board_num;		/* Board number from SPROM. */
+	u16 board_type;		/* Board type from SPROM. */
 	u8 country_code;	/* Country Code */
-	u16 leddc_on_time;	/* LED Powersave Duty Cycle On Count */
-	u16 leddc_off_time;	/* LED Powersave Duty Cycle Off Count */
+	char alpha2[2];		/* Country Code as two chars like EU or US */
+	u8 leddc_on_time;	/* LED Powersave Duty Cycle On Count */
+	u8 leddc_off_time;	/* LED Powersave Duty Cycle Off Count */
 	u8 ant_available_a;	/* 2GHz antenna available bits (up to 4) */
 	u8 ant_available_bg;	/* 5GHz antenna available bits (up to 4) */
 	u16 pa0b0;
@@ -47,10 +56,10 @@
 	u8 gpio1;		/* GPIO pin 1 */
 	u8 gpio2;		/* GPIO pin 2 */
 	u8 gpio3;		/* GPIO pin 3 */
-	u16 maxpwr_bg;		/* 2.4GHz Amplifier Max Power (in dBm Q5.2) */
-	u16 maxpwr_al;		/* 5.2GHz Amplifier Max Power (in dBm Q5.2) */
-	u16 maxpwr_a;		/* 5.3GHz Amplifier Max Power (in dBm Q5.2) */
-	u16 maxpwr_ah;		/* 5.8GHz Amplifier Max Power (in dBm Q5.2) */
+	u8 maxpwr_bg;		/* 2.4GHz Amplifier Max Power (in dBm Q5.2) */
+	u8 maxpwr_al;		/* 5.2GHz Amplifier Max Power (in dBm Q5.2) */
+	u8 maxpwr_a;		/* 5.3GHz Amplifier Max Power (in dBm Q5.2) */
+	u8 maxpwr_ah;		/* 5.8GHz Amplifier Max Power (in dBm Q5.2) */
 	u8 itssi_a;		/* Idle TSSI Target for A-PHY */
 	u8 itssi_bg;		/* Idle TSSI Target for B/G-PHY */
 	u8 tri2g;		/* 2.4GHz TX isolation */
@@ -61,8 +70,8 @@
 	u8 txpid5gl[4];		/* 4.9 - 5.1GHz TX power index */
 	u8 txpid5g[4];		/* 5.1 - 5.5GHz TX power index */
 	u8 txpid5gh[4];		/* 5.5 - ...GHz TX power index */
-	u8 rxpo2g;		/* 2GHz RX power offset */
-	u8 rxpo5g;		/* 5GHz RX power offset */
+	s8 rxpo2g;		/* 2GHz RX power offset */
+	s8 rxpo5g;		/* 5GHz RX power offset */
 	u8 rssisav2g;		/* 2GHz RSSI params */
 	u8 rssismc2g;
 	u8 rssismf2g;
@@ -82,16 +91,13 @@
 	u16 boardflags2_hi;	/* Board flags (bits 48-63) */
 	/* TODO store board flags in a single u64 */
 
+	struct ssb_sprom_core_pwr_info core_pwr_info[4];
+
 	/* Antenna gain values for up to 4 antennas
 	 * on each band. Values in dBm/4 (Q5.2). Negative gain means the
 	 * loss in the connectors is bigger than the gain. */
 	struct {
-		struct {
-			s8 a0, a1, a2, a3;
-		} ghz24;	/* 2.4GHz band */
-		struct {
-			s8 a0, a1, a2, a3;
-		} ghz5;		/* 5GHz band */
+		s8 a0, a1, a2, a3;
 	} antenna_gain;
 
 	struct {
@@ -103,14 +109,85 @@
 		} ghz5;
 	} fem;
 
-	/* TODO - add any parameters needed from rev 2, 3, 4, 5 or 8 SPROMs */
+	u16 mcs2gpo[8];
+	u16 mcs5gpo[8];
+	u16 mcs5glpo[8];
+	u16 mcs5ghpo[8];
+	u8 opo;
+
+	u8 rxgainerr2ga[3];
+	u8 rxgainerr5gla[3];
+	u8 rxgainerr5gma[3];
+	u8 rxgainerr5gha[3];
+	u8 rxgainerr5gua[3];
+
+	u8 noiselvl2ga[3];
+	u8 noiselvl5gla[3];
+	u8 noiselvl5gma[3];
+	u8 noiselvl5gha[3];
+	u8 noiselvl5gua[3];
+
+	u8 regrev;
+	u8 txchain;
+	u8 rxchain;
+	u8 antswitch;
+	u16 cddpo;
+	u16 stbcpo;
+	u16 bw40po;
+	u16 bwduppo;
+
+	u8 tempthresh;
+	u8 tempoffset;
+	u16 rawtempsense;
+	u8 measpower;
+	u8 tempsense_slope;
+	u8 tempcorrx;
+	u8 tempsense_option;
+	u8 freqoffset_corr;
+	u8 iqcal_swp_dis;
+	u8 hw_iqcal_en;
+	u8 elna2g;
+	u8 elna5g;
+	u8 phycal_tempdelta;
+	u8 temps_period;
+	u8 temps_hysteresis;
+	u8 measpower1;
+	u8 measpower2;
+	u8 pcieingress_war;
+
+	/* power per rate from sromrev 9 */
+	u16 cckbw202gpo;
+	u16 cckbw20ul2gpo;
+	u32 legofdmbw202gpo;
+	u32 legofdmbw20ul2gpo;
+	u32 legofdmbw205glpo;
+	u32 legofdmbw20ul5glpo;
+	u32 legofdmbw205gmpo;
+	u32 legofdmbw20ul5gmpo;
+	u32 legofdmbw205ghpo;
+	u32 legofdmbw20ul5ghpo;
+	u32 mcsbw202gpo;
+	u32 mcsbw20ul2gpo;
+	u32 mcsbw402gpo;
+	u32 mcsbw205glpo;
+	u32 mcsbw20ul5glpo;
+	u32 mcsbw405glpo;
+	u32 mcsbw205gmpo;
+	u32 mcsbw20ul5gmpo;
+	u32 mcsbw405gmpo;
+	u32 mcsbw205ghpo;
+	u32 mcsbw20ul5ghpo;
+	u32 mcsbw405ghpo;
+	u16 mcs32po;
+	u16 legofdm40duppo;
+	u8 sar2g;
+	u8 sar5g;
 };
 
 /* Information about the PCB the circuitry is soldered on. */
 struct ssb_boardinfo {
 	u16 vendor;
 	u16 type;
-	u8  rev;
 };
 
 
@@ -166,6 +243,7 @@
 #define SSB_DEV_MINI_MACPHY	0x823
 #define SSB_DEV_ARM_1176	0x824
 #define SSB_DEV_ARM_7TDMI	0x825
+#define SSB_DEV_ARM_CM3		0x82A
 
 /* Vendor-ID values */
 #define SSB_VENDOR_BROADCOM	0x4243
diff --git a/include/linux/ssb/ssb_driver_gige.h b/include/linux/ssb/ssb_driver_gige.h
index eba52a1..6b05dcd 100644
--- a/include/linux/ssb/ssb_driver_gige.h
+++ b/include/linux/ssb/ssb_driver_gige.h
@@ -2,6 +2,7 @@
 #define LINUX_SSB_DRIVER_GIGE_H_
 
 #include <linux/ssb/ssb.h>
+#include <linux/bug.h>
 #include <linux/pci.h>
 #include <linux/spinlock.h>
 
diff --git a/include/linux/ssb/ssb_regs.h b/include/linux/ssb/ssb_regs.h
index c814ae6..a052501 100644
--- a/include/linux/ssb/ssb_regs.h
+++ b/include/linux/ssb/ssb_regs.h
@@ -228,6 +228,7 @@
 #define  SSB_SPROM1_AGAIN_BG_SHIFT	0
 #define  SSB_SPROM1_AGAIN_A		0xFF00	/* A-PHY */
 #define  SSB_SPROM1_AGAIN_A_SHIFT	8
+#define SSB_SPROM1_CCODE		0x0076
 
 /* SPROM Revision 2 (inherits from rev 1) */
 #define SSB_SPROM2_BFLHI		0x0038	/* Boardflags (high 16 bits) */
@@ -267,6 +268,7 @@
 #define  SSB_SPROM3_OFDMGPO		0x107A	/* G-PHY OFDM Power Offset (4 bytes, BigEndian) */
 
 /* SPROM Revision 4 */
+#define SSB_SPROM4_BOARDREV		0x0042	/* Board revision */
 #define SSB_SPROM4_BFLLO		0x0044	/* Boardflags (low 16 bits) */
 #define SSB_SPROM4_BFLHI		0x0046  /* Board Flags Hi */
 #define SSB_SPROM4_BFL2LO		0x0048	/* Board flags 2 (low 16 bits) */
@@ -389,6 +391,11 @@
 #define  SSB_SPROM8_GPIOB_P2		0x00FF	/* Pin 2 */
 #define  SSB_SPROM8_GPIOB_P3		0xFF00	/* Pin 3 */
 #define  SSB_SPROM8_GPIOB_P3_SHIFT	8
+#define SSB_SPROM8_LEDDC		0x009A
+#define  SSB_SPROM8_LEDDC_ON		0xFF00	/* oncount */
+#define  SSB_SPROM8_LEDDC_ON_SHIFT	8
+#define  SSB_SPROM8_LEDDC_OFF		0x00FF	/* offcount */
+#define  SSB_SPROM8_LEDDC_OFF_SHIFT	0
 #define SSB_SPROM8_ANTAVAIL		0x009C  /* Antenna available bitfields*/
 #define  SSB_SPROM8_ANTAVAIL_A		0xFF00	/* A-PHY bitfield */
 #define  SSB_SPROM8_ANTAVAIL_A_SHIFT	8
@@ -404,6 +411,13 @@
 #define  SSB_SPROM8_AGAIN2_SHIFT	0
 #define  SSB_SPROM8_AGAIN3		0xFF00	/* Antenna 3 */
 #define  SSB_SPROM8_AGAIN3_SHIFT	8
+#define SSB_SPROM8_TXRXC		0x00A2
+#define  SSB_SPROM8_TXRXC_TXCHAIN	0x000f
+#define  SSB_SPROM8_TXRXC_TXCHAIN_SHIFT	0
+#define  SSB_SPROM8_TXRXC_RXCHAIN	0x00f0
+#define  SSB_SPROM8_TXRXC_RXCHAIN_SHIFT	4
+#define  SSB_SPROM8_TXRXC_SWITCH	0xff00
+#define  SSB_SPROM8_TXRXC_SWITCH_SHIFT	8
 #define SSB_SPROM8_RSSIPARM2G		0x00A4	/* RSSI params for 2GHz */
 #define  SSB_SPROM8_RSSISMF2G		0x000F
 #define  SSB_SPROM8_RSSISMC2G		0x00F0
@@ -430,6 +444,7 @@
 #define  SSB_SPROM8_TRI5GH_SHIFT	8
 #define SSB_SPROM8_RXPO			0x00AC  /* RX power offsets */
 #define  SSB_SPROM8_RXPO2G		0x00FF	/* 2GHz RX power offset */
+#define  SSB_SPROM8_RXPO2G_SHIFT	0
 #define  SSB_SPROM8_RXPO5G		0xFF00	/* 5GHz RX power offset */
 #define  SSB_SPROM8_RXPO5G_SHIFT	8
 #define SSB_SPROM8_FEM2G		0x00AE
@@ -445,10 +460,71 @@
 #define  SSB_SROM8_FEM_ANTSWLUT		0xF800
 #define  SSB_SROM8_FEM_ANTSWLUT_SHIFT	11
 #define SSB_SPROM8_THERMAL		0x00B2
-#define SSB_SPROM8_MPWR_RAWTS		0x00B4
-#define SSB_SPROM8_TS_SLP_OPT_CORRX	0x00B6
-#define SSB_SPROM8_FOC_HWIQ_IQSWP	0x00B8
-#define SSB_SPROM8_PHYCAL_TEMPDELTA	0x00BA
+#define  SSB_SPROM8_THERMAL_OFFSET	0x00ff
+#define  SSB_SPROM8_THERMAL_OFFSET_SHIFT	0
+#define  SSB_SPROM8_THERMAL_TRESH	0xff00
+#define  SSB_SPROM8_THERMAL_TRESH_SHIFT	8
+/* Temp sense related entries */
+#define SSB_SPROM8_RAWTS		0x00B4
+#define  SSB_SPROM8_RAWTS_RAWTEMP	0x01ff
+#define  SSB_SPROM8_RAWTS_RAWTEMP_SHIFT	0
+#define  SSB_SPROM8_RAWTS_MEASPOWER	0xfe00
+#define  SSB_SPROM8_RAWTS_MEASPOWER_SHIFT	9
+#define SSB_SPROM8_OPT_CORRX		0x00B6
+#define  SSB_SPROM8_OPT_CORRX_TEMP_SLOPE	0x00ff
+#define  SSB_SPROM8_OPT_CORRX_TEMP_SLOPE_SHIFT	0
+#define  SSB_SPROM8_OPT_CORRX_TEMPCORRX	0xfc00
+#define  SSB_SPROM8_OPT_CORRX_TEMPCORRX_SHIFT	10
+#define  SSB_SPROM8_OPT_CORRX_TEMP_OPTION	0x0300
+#define  SSB_SPROM8_OPT_CORRX_TEMP_OPTION_SHIFT	8
+/* FOC: freiquency offset correction, HWIQ: H/W IOCAL enable, IQSWP: IQ CAL swap disable */
+#define SSB_SPROM8_HWIQ_IQSWP		0x00B8
+#define  SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR	0x000f
+#define  SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR_SHIFT	0
+#define  SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP	0x0010
+#define  SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT	4
+#define  SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL	0x0020
+#define  SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT	5
+#define SSB_SPROM8_TEMPDELTA		0x00BA
+#define  SSB_SPROM8_TEMPDELTA_PHYCAL	0x00ff
+#define  SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT	0
+#define  SSB_SPROM8_TEMPDELTA_PERIOD	0x0f00
+#define  SSB_SPROM8_TEMPDELTA_PERIOD_SHIFT	8
+#define  SSB_SPROM8_TEMPDELTA_HYSTERESIS	0xf000
+#define  SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT	12
+
+/* There are 4 blocks with power info sharing the same layout */
+#define SSB_SROM8_PWR_INFO_CORE0	0x00C0
+#define SSB_SROM8_PWR_INFO_CORE1	0x00E0
+#define SSB_SROM8_PWR_INFO_CORE2	0x0100
+#define SSB_SROM8_PWR_INFO_CORE3	0x0120
+
+#define SSB_SROM8_2G_MAXP_ITSSI		0x00
+#define  SSB_SPROM8_2G_MAXP		0x00FF
+#define  SSB_SPROM8_2G_ITSSI		0xFF00
+#define  SSB_SPROM8_2G_ITSSI_SHIFT	8
+#define SSB_SROM8_2G_PA_0		0x02	/* 2GHz power amp settings */
+#define SSB_SROM8_2G_PA_1		0x04
+#define SSB_SROM8_2G_PA_2		0x06
+#define SSB_SROM8_5G_MAXP_ITSSI		0x08	/* 5GHz ITSSI and 5.3GHz Max Power */
+#define  SSB_SPROM8_5G_MAXP		0x00FF
+#define  SSB_SPROM8_5G_ITSSI		0xFF00
+#define  SSB_SPROM8_5G_ITSSI_SHIFT	8
+#define SSB_SPROM8_5GHL_MAXP		0x0A	/* 5.2GHz and 5.8GHz Max Power */
+#define  SSB_SPROM8_5GH_MAXP		0x00FF
+#define  SSB_SPROM8_5GL_MAXP		0xFF00
+#define  SSB_SPROM8_5GL_MAXP_SHIFT	8
+#define SSB_SROM8_5G_PA_0		0x0C	/* 5.3GHz power amp settings */
+#define SSB_SROM8_5G_PA_1		0x0E
+#define SSB_SROM8_5G_PA_2		0x10
+#define SSB_SROM8_5GL_PA_0		0x12	/* 5.2GHz power amp settings */
+#define SSB_SROM8_5GL_PA_1		0x14
+#define SSB_SROM8_5GL_PA_2		0x16
+#define SSB_SROM8_5GH_PA_0		0x18	/* 5.8GHz power amp settings */
+#define SSB_SROM8_5GH_PA_1		0x1A
+#define SSB_SROM8_5GH_PA_2		0x1C
+
+/* TODO: Make it deprecated */
 #define SSB_SPROM8_MAXP_BG		0x00C0  /* Max Power 2GHz in path 1 */
 #define  SSB_SPROM8_MAXP_BG_MASK	0x00FF  /* Mask for Max Power 2GHz */
 #define  SSB_SPROM8_ITSSI_BG		0xFF00	/* Mask for path 1 itssi_bg */
@@ -473,12 +549,23 @@
 #define SSB_SPROM8_PA1HIB0		0x00D8	/* 5.8GHz power amp settings */
 #define SSB_SPROM8_PA1HIB1		0x00DA
 #define SSB_SPROM8_PA1HIB2		0x00DC
+
 #define SSB_SPROM8_CCK2GPO		0x0140	/* CCK power offset */
 #define SSB_SPROM8_OFDM2GPO		0x0142	/* 2.4GHz OFDM power offset */
 #define SSB_SPROM8_OFDM5GPO		0x0146	/* 5.3GHz OFDM power offset */
 #define SSB_SPROM8_OFDM5GLPO		0x014A	/* 5.2GHz OFDM power offset */
 #define SSB_SPROM8_OFDM5GHPO		0x014E	/* 5.8GHz OFDM power offset */
 
+#define SSB_SPROM8_2G_MCSPO		0x0152
+#define SSB_SPROM8_5G_MCSPO		0x0162
+#define SSB_SPROM8_5GL_MCSPO		0x0172
+#define SSB_SPROM8_5GH_MCSPO		0x0182
+
+#define SSB_SPROM8_CDDPO		0x0192
+#define SSB_SPROM8_STBCPO		0x0194
+#define SSB_SPROM8_BW40PO		0x0196
+#define SSB_SPROM8_BWDUPPO		0x0198
+
 /* Values for boardflags_lo read from SPROM */
 #define SSB_BFL_BTCOEXIST		0x0001	/* implements Bluetooth coexistance */
 #define SSB_BFL_PACTRL			0x0002	/* GPIO 9 controlling the PA */
diff --git a/include/linux/stddef.h b/include/linux/stddef.h
index 6a40c76..5dab46c 100644
--- a/include/linux/stddef.h
+++ b/include/linux/stddef.h
@@ -16,6 +16,7 @@
 	false	= 0,
 	true	= 1
 };
+#endif /* __KERNEL__ */
 
 #undef offsetof
 #ifdef __compiler_offsetof
@@ -23,6 +24,5 @@
 #else
 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
 #endif
-#endif /* __KERNEL__ */
 
 #endif
diff --git a/include/linux/usb.h b/include/linux/usb.h
index c3ba767..93df11e 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -531,6 +531,7 @@
 extern int usb_reset_device(struct usb_device *dev);
 extern void usb_queue_reset_device(struct usb_interface *dev);
 
+extern struct usb_device *usb_find_device_by_name(const char *name);
 
 /* USB autosuspend and autoresume */
 #ifdef CONFIG_USB_SUSPEND
diff --git a/include/mtd/mtd-abi.h b/include/mtd/mtd-abi.h
index 36eace0..3ee7975 100644
--- a/include/mtd/mtd-abi.h
+++ b/include/mtd/mtd-abi.h
@@ -202,6 +202,7 @@
  * without OOB, e.g., NOR flash.
  */
 #define MEMWRITE		_IOWR('M', 24, struct mtd_write_req)
+#define MTDREFRESH		_IO('M', 50)
 
 /*
  * Obsolete legacy interface. Keep it in order not to break userspace
diff --git a/include/net/Kbuild b/include/net/Kbuild
new file mode 100644
index 0000000..3a0d19a
--- /dev/null
+++ b/include/net/Kbuild
@@ -0,0 +1 @@
+header-y += switch.h
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index f68dce2..4de7092 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -91,6 +91,12 @@
 extern void			addrconf_leave_solict(struct inet6_dev *idev,
 					const struct in6_addr *addr);
 
+extern int			(*ipv6_dev_get_saddr_hook)(struct net *net,
+						struct net_device *dev,
+						const struct in6_addr *daddr,
+						unsigned int srcprefs,
+						struct in6_addr *saddr);
+
 static inline unsigned long addrconf_timeout_fixup(u32 timeout,
 						    unsigned unit)
 {
diff --git a/include/net/codel.h b/include/net/codel.h
new file mode 100644
index 0000000..389cf62
--- /dev/null
+++ b/include/net/codel.h
@@ -0,0 +1,346 @@
+#ifndef __NET_SCHED_CODEL_H
+#define __NET_SCHED_CODEL_H
+
+/*
+ * Codel - The Controlled-Delay Active Queue Management algorithm
+ *
+ *  Copyright (C) 2011-2012 Kathleen Nichols <nichols@pollere.com>
+ *  Copyright (C) 2011-2012 Van Jacobson <van@pollere.net>
+ *  Copyright (C) 2012 Michael D. Taht <dave.taht@bufferbloat.net>
+ *  Copyright (C) 2012 Eric Dumazet <edumazet@google.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The names of the authors may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, provided that this notice is retained in full, this
+ * software may be distributed under the terms of the GNU General
+ * Public License ("GPL") version 2, in which case the provisions of the
+ * GPL apply INSTEAD OF those given above.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/ktime.h>
+#include <linux/skbuff.h>
+#include <net/pkt_sched.h>
+#include <net/inet_ecn.h>
+#include <linux/reciprocal_div.h>
+
+/* Controlling Queue Delay (CoDel) algorithm
+ * =========================================
+ * Source : Kathleen Nichols and Van Jacobson
+ * http://queue.acm.org/detail.cfm?id=2209336
+ *
+ * Implemented on linux by Dave Taht and Eric Dumazet
+ */
+
+
+/* CoDel uses a 1024 nsec clock, encoded in u32
+ * This gives a range of 2199 seconds, because of signed compares
+ */
+typedef u32 codel_time_t;
+typedef s32 codel_tdiff_t;
+#define CODEL_SHIFT 10
+#define MS2TIME(a) ((a * NSEC_PER_MSEC) >> CODEL_SHIFT)
+
+static inline codel_time_t codel_get_time(void)
+{
+	u64 ns = ktime_to_ns(ktime_get());
+
+	return ns >> CODEL_SHIFT;
+}
+
+#define codel_time_after(a, b)		((s32)(a) - (s32)(b) > 0)
+#define codel_time_after_eq(a, b)	((s32)(a) - (s32)(b) >= 0)
+#define codel_time_before(a, b)		((s32)(a) - (s32)(b) < 0)
+#define codel_time_before_eq(a, b)	((s32)(a) - (s32)(b) <= 0)
+
+/* Qdiscs using codel plugin must use codel_skb_cb in their own cb[] */
+struct codel_skb_cb {
+	codel_time_t enqueue_time;
+};
+
+static struct codel_skb_cb *get_codel_cb(const struct sk_buff *skb)
+{
+	qdisc_cb_private_validate(skb, sizeof(struct codel_skb_cb));
+	return (struct codel_skb_cb *)qdisc_skb_cb(skb)->data;
+}
+
+static codel_time_t codel_get_enqueue_time(const struct sk_buff *skb)
+{
+	return get_codel_cb(skb)->enqueue_time;
+}
+
+static void codel_set_enqueue_time(struct sk_buff *skb)
+{
+	get_codel_cb(skb)->enqueue_time = codel_get_time();
+}
+
+static inline u32 codel_time_to_us(codel_time_t val)
+{
+	u64 valns = ((u64)val << CODEL_SHIFT);
+
+	do_div(valns, NSEC_PER_USEC);
+	return (u32)valns;
+}
+
+/**
+ * struct codel_params - contains codel parameters
+ * @target:	target queue size (in time units)
+ * @interval:	width of moving time window
+ * @ecn:	is Explicit Congestion Notification enabled
+ */
+struct codel_params {
+	codel_time_t	target;
+	codel_time_t	interval;
+	bool		ecn;
+};
+
+/**
+ * struct codel_vars - contains codel variables
+ * @count:		how many drops we've done since the last time we
+ *			entered dropping state
+ * @lastcount:		count at entry to dropping state
+ * @dropping:		set to true if in dropping state
+ * @rec_inv_sqrt:	reciprocal value of sqrt(count) >> 1
+ * @first_above_time:	when we went (or will go) continuously above target
+ *			for interval
+ * @drop_next:		time to drop next packet, or when we dropped last
+ * @ldelay:		sojourn time of last dequeued packet
+ */
+struct codel_vars {
+	u32		count;
+	u32		lastcount;
+	bool		dropping;
+	u16		rec_inv_sqrt;
+	codel_time_t	first_above_time;
+	codel_time_t	drop_next;
+	codel_time_t	ldelay;
+};
+
+#define REC_INV_SQRT_BITS (8 * sizeof(u16)) /* or sizeof_in_bits(rec_inv_sqrt) */
+/* needed shift to get a Q0.32 number from rec_inv_sqrt */
+#define REC_INV_SQRT_SHIFT (32 - REC_INV_SQRT_BITS)
+
+/**
+ * struct codel_stats - contains codel shared variables and stats
+ * @maxpacket:	largest packet we've seen so far
+ * @drop_count:	temp count of dropped packets in dequeue()
+ * ecn_mark:	number of packets we ECN marked instead of dropping
+ */
+struct codel_stats {
+	u32		maxpacket;
+	u32		drop_count;
+	u32		ecn_mark;
+};
+
+static void codel_params_init(struct codel_params *params)
+{
+	params->interval = MS2TIME(100);
+	params->target = MS2TIME(5);
+	params->ecn = false;
+}
+
+static void codel_vars_init(struct codel_vars *vars)
+{
+	memset(vars, 0, sizeof(*vars));
+}
+
+static void codel_stats_init(struct codel_stats *stats)
+{
+	stats->maxpacket = 256;
+}
+
+/*
+ * http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Iterative_methods_for_reciprocal_square_roots
+ * new_invsqrt = (invsqrt / 2) * (3 - count * invsqrt^2)
+ *
+ * Here, invsqrt is a fixed point number (< 1.0), 32bit mantissa, aka Q0.32
+ */
+static void codel_Newton_step(struct codel_vars *vars)
+{
+	u32 invsqrt = ((u32)vars->rec_inv_sqrt) << REC_INV_SQRT_SHIFT;
+	u32 invsqrt2 = ((u64)invsqrt * invsqrt) >> 32;
+	u64 val = (3LL << 32) - ((u64)vars->count * invsqrt2);
+
+	val >>= 2; /* avoid overflow in following multiply */
+	val = (val * invsqrt) >> (32 - 2 + 1);
+
+	vars->rec_inv_sqrt = val >> REC_INV_SQRT_SHIFT;
+}
+
+/*
+ * CoDel control_law is t + interval/sqrt(count)
+ * We maintain in rec_inv_sqrt the reciprocal value of sqrt(count) to avoid
+ * both sqrt() and divide operation.
+ */
+static codel_time_t codel_control_law(codel_time_t t,
+				      codel_time_t interval,
+				      u32 rec_inv_sqrt)
+{
+	return t + reciprocal_divide(interval, rec_inv_sqrt << REC_INV_SQRT_SHIFT);
+}
+
+
+static bool codel_should_drop(const struct sk_buff *skb,
+			      struct Qdisc *sch,
+			      struct codel_vars *vars,
+			      struct codel_params *params,
+			      struct codel_stats *stats,
+			      codel_time_t now)
+{
+	bool ok_to_drop;
+
+	if (!skb) {
+		vars->first_above_time = 0;
+		return false;
+	}
+
+	vars->ldelay = now - codel_get_enqueue_time(skb);
+	sch->qstats.backlog -= qdisc_pkt_len(skb);
+
+	if (unlikely(qdisc_pkt_len(skb) > stats->maxpacket))
+		stats->maxpacket = qdisc_pkt_len(skb);
+
+	if (codel_time_before(vars->ldelay, params->target) ||
+	    sch->qstats.backlog <= stats->maxpacket) {
+		/* went below - stay below for at least interval */
+		vars->first_above_time = 0;
+		return false;
+	}
+	ok_to_drop = false;
+	if (vars->first_above_time == 0) {
+		/* just went above from below. If we stay above
+		 * for at least interval we'll say it's ok to drop
+		 */
+		vars->first_above_time = now + params->interval;
+	} else if (codel_time_after(now, vars->first_above_time)) {
+		ok_to_drop = true;
+	}
+	return ok_to_drop;
+}
+
+typedef struct sk_buff * (*codel_skb_dequeue_t)(struct codel_vars *vars,
+						struct Qdisc *sch);
+
+static struct sk_buff *codel_dequeue(struct Qdisc *sch,
+				     struct codel_params *params,
+				     struct codel_vars *vars,
+				     struct codel_stats *stats,
+				     codel_skb_dequeue_t dequeue_func)
+{
+	struct sk_buff *skb = dequeue_func(vars, sch);
+	codel_time_t now;
+	bool drop;
+
+	if (!skb) {
+		vars->dropping = false;
+		return skb;
+	}
+	now = codel_get_time();
+	drop = codel_should_drop(skb, sch, vars, params, stats, now);
+	if (vars->dropping) {
+		if (!drop) {
+			/* sojourn time below target - leave dropping state */
+			vars->dropping = false;
+		} else if (codel_time_after_eq(now, vars->drop_next)) {
+			/* It's time for the next drop. Drop the current
+			 * packet and dequeue the next. The dequeue might
+			 * take us out of dropping state.
+			 * If not, schedule the next drop.
+			 * A large backlog might result in drop rates so high
+			 * that the next drop should happen now,
+			 * hence the while loop.
+			 */
+			while (vars->dropping &&
+			       codel_time_after_eq(now, vars->drop_next)) {
+				vars->count++; /* dont care of possible wrap
+						* since there is no more divide
+						*/
+				codel_Newton_step(vars);
+				if (params->ecn && INET_ECN_set_ce(skb)) {
+					stats->ecn_mark++;
+					vars->drop_next =
+						codel_control_law(vars->drop_next,
+								  params->interval,
+								  vars->rec_inv_sqrt);
+					goto end;
+				}
+				qdisc_drop(skb, sch);
+				stats->drop_count++;
+				skb = dequeue_func(vars, sch);
+				if (!codel_should_drop(skb, sch,
+						       vars, params, stats, now)) {
+					/* leave dropping state */
+					vars->dropping = false;
+				} else {
+					/* and schedule the next drop */
+					vars->drop_next =
+						codel_control_law(vars->drop_next,
+								  params->interval,
+								  vars->rec_inv_sqrt);
+				}
+			}
+		}
+	} else if (drop) {
+		u32 delta;
+
+		if (params->ecn && INET_ECN_set_ce(skb)) {
+			stats->ecn_mark++;
+		} else {
+			qdisc_drop(skb, sch);
+			stats->drop_count++;
+
+			skb = dequeue_func(vars, sch);
+			drop = codel_should_drop(skb, sch, vars, params,
+						 stats, now);
+		}
+		vars->dropping = true;
+		/* if min went above target close to when we last went below it
+		 * assume that the drop rate that controlled the queue on the
+		 * last cycle is a good starting point to control it now.
+		 */
+		delta = vars->count - vars->lastcount;
+		if (delta > 1 &&
+		    codel_time_before(now - vars->drop_next,
+				      16 * params->interval)) {
+			vars->count = delta;
+			/* we dont care if rec_inv_sqrt approximation
+			 * is not very precise :
+			 * Next Newton steps will correct it quadratically.
+			 */
+			codel_Newton_step(vars);
+		} else {
+			vars->count = 1;
+			vars->rec_inv_sqrt = ~0U >> REC_INV_SQRT_SHIFT;
+		}
+		vars->lastcount = vars->count;
+		vars->drop_next = codel_control_law(now, params->interval,
+						    vars->rec_inv_sqrt);
+	}
+end:
+	return skb;
+}
+#endif
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index ab86036..6efff6f 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -134,6 +134,22 @@
 	struct net *ct_net;
 #endif
 
+#if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || \
+    defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE)
+	struct {
+		/*
+		 * e.g. "http". NULL before decision. "unknown" after decision
+		 * if no match.
+		 */
+		char *app_proto;
+		/*
+		 * application layer data so far. NULL after match decision.
+		 */
+		char *app_data;
+		unsigned int app_data_len;
+	} layer7;
+#endif
+
 	/* Storage reserved for other modules, must be the last member */
 	union nf_conntrack_proto proto;
 };
diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h
index a88fb69..923fb94 100644
--- a/include/net/netfilter/nf_conntrack_ecache.h
+++ b/include/net/netfilter/nf_conntrack_ecache.h
@@ -63,12 +63,18 @@
 	int report;
 };
 
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+extern struct atomic_notifier_head nf_conntrack_chain;
+extern int nf_conntrack_register_notifier(struct net *net, struct notifier_block *nb);
+extern int nf_conntrack_unregister_notifier(struct net *net, struct notifier_block *nb);
+#else
 struct nf_ct_event_notifier {
 	int (*fcn)(unsigned int events, struct nf_ct_event *item);
 };
 
 extern int nf_conntrack_register_notifier(struct net *net, struct nf_ct_event_notifier *nb);
 extern void nf_conntrack_unregister_notifier(struct net *net, struct nf_ct_event_notifier *nb);
+#endif
 
 extern void nf_ct_deliver_cached_events(struct nf_conn *ct);
 
@@ -78,8 +84,10 @@
 	struct net *net = nf_ct_net(ct);
 	struct nf_conntrack_ecache *e;
 
+#ifndef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
 	if (net->ct.nf_conntrack_event_cb == NULL)
 		return;
+#endif
 
 	e = nf_ct_ecache_find(ct);
 	if (e == NULL)
@@ -96,13 +104,15 @@
 {
 	int ret = 0;
 	struct net *net = nf_ct_net(ct);
-	struct nf_ct_event_notifier *notify;
 	struct nf_conntrack_ecache *e;
+#ifndef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+	struct nf_ct_event_notifier *notify;
 
 	rcu_read_lock();
 	notify = rcu_dereference(net->ct.nf_conntrack_event_cb);
 	if (notify == NULL)
 		goto out_unlock;
+#endif
 
 	e = nf_ct_ecache_find(ct);
 	if (e == NULL)
@@ -120,6 +130,10 @@
 		if (!((eventmask | missed) & e->ctmask))
 			goto out_unlock;
 
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+		atomic_notifier_call_chain(&nf_conntrack_chain, eventmask | missed, &item);
+#else
+
 		ret = notify->fcn(eventmask | missed, &item);
 		if (unlikely(ret < 0 || missed)) {
 			spin_lock_bh(&ct->lock);
@@ -136,9 +150,12 @@
 				e->missed &= ~missed;
 			spin_unlock_bh(&ct->lock);
 		}
+#endif
 	}
 out_unlock:
+#ifndef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
 	rcu_read_unlock();
+#endif
 	return ret;
 }
 
diff --git a/include/net/sock.h b/include/net/sock.h
index 91c1c8b..260070a 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -810,6 +810,8 @@
 	int			(*backlog_rcv) (struct sock *sk, 
 						struct sk_buff *skb);
 
+	void		(*release_cb)(struct sock *sk);
+
 	/* Keeping track of sk's, looking them up, and port selection methods. */
 	void			(*hash)(struct sock *sk);
 	void			(*unhash)(struct sock *sk);
diff --git a/include/trace/events/random.h b/include/trace/events/random.h
new file mode 100644
index 0000000..422df19
--- /dev/null
+++ b/include/trace/events/random.h
@@ -0,0 +1,134 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM random
+
+#if !defined(_TRACE_RANDOM_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_RANDOM_H
+
+#include <linux/writeback.h>
+#include <linux/tracepoint.h>
+
+DECLARE_EVENT_CLASS(random__mix_pool_bytes,
+	TP_PROTO(const char *pool_name, int bytes, unsigned long IP),
+
+	TP_ARGS(pool_name, bytes, IP),
+
+	TP_STRUCT__entry(
+		__field( const char *,	pool_name		)
+		__field(	  int,	bytes			)
+		__field(unsigned long,	IP			)
+	),
+
+	TP_fast_assign(
+		__entry->pool_name	= pool_name;
+		__entry->bytes		= bytes;
+		__entry->IP		= IP;
+	),
+
+	TP_printk("%s pool: bytes %d caller %pF",
+		  __entry->pool_name, __entry->bytes, (void *)__entry->IP)
+);
+
+DEFINE_EVENT(random__mix_pool_bytes, mix_pool_bytes,
+	TP_PROTO(const char *pool_name, int bytes, unsigned long IP),
+
+	TP_ARGS(pool_name, bytes, IP)
+);
+
+DEFINE_EVENT(random__mix_pool_bytes, mix_pool_bytes_nolock,
+	TP_PROTO(const char *pool_name, int bytes, unsigned long IP),
+
+	TP_ARGS(pool_name, bytes, IP)
+);
+
+TRACE_EVENT(credit_entropy_bits,
+	TP_PROTO(const char *pool_name, int bits, int entropy_count,
+		 int entropy_total, unsigned long IP),
+
+	TP_ARGS(pool_name, bits, entropy_count, entropy_total, IP),
+
+	TP_STRUCT__entry(
+		__field( const char *,	pool_name		)
+		__field(	  int,	bits			)
+		__field(	  int,	entropy_count		)
+		__field(	  int,	entropy_total		)
+		__field(unsigned long,	IP			)
+	),
+
+	TP_fast_assign(
+		__entry->pool_name	= pool_name;
+		__entry->bits		= bits;
+		__entry->entropy_count	= entropy_count;
+		__entry->entropy_total	= entropy_total;
+		__entry->IP		= IP;
+	),
+
+	TP_printk("%s pool: bits %d entropy_count %d entropy_total %d "
+		  "caller %pF", __entry->pool_name, __entry->bits,
+		  __entry->entropy_count, __entry->entropy_total,
+		  (void *)__entry->IP)
+);
+
+TRACE_EVENT(get_random_bytes,
+	TP_PROTO(int nbytes, unsigned long IP),
+
+	TP_ARGS(nbytes, IP),
+
+	TP_STRUCT__entry(
+		__field(	  int,	nbytes			)
+		__field(unsigned long,	IP			)
+	),
+
+	TP_fast_assign(
+		__entry->nbytes		= nbytes;
+		__entry->IP		= IP;
+	),
+
+	TP_printk("nbytes %d caller %pF", __entry->nbytes, (void *)__entry->IP)
+);
+
+DECLARE_EVENT_CLASS(random__extract_entropy,
+	TP_PROTO(const char *pool_name, int nbytes, int entropy_count,
+		 unsigned long IP),
+
+	TP_ARGS(pool_name, nbytes, entropy_count, IP),
+
+	TP_STRUCT__entry(
+		__field( const char *,	pool_name		)
+		__field(	  int,	nbytes			)
+		__field(	  int,	entropy_count		)
+		__field(unsigned long,	IP			)
+	),
+
+	TP_fast_assign(
+		__entry->pool_name	= pool_name;
+		__entry->nbytes		= nbytes;
+		__entry->entropy_count	= entropy_count;
+		__entry->IP		= IP;
+	),
+
+	TP_printk("%s pool: nbytes %d entropy_count %d caller %pF",
+		  __entry->pool_name, __entry->nbytes, __entry->entropy_count,
+		  (void *)__entry->IP)
+);
+
+
+DEFINE_EVENT(random__extract_entropy, extract_entropy,
+	TP_PROTO(const char *pool_name, int nbytes, int entropy_count,
+		 unsigned long IP),
+
+	TP_ARGS(pool_name, nbytes, entropy_count, IP)
+);
+
+DEFINE_EVENT(random__extract_entropy, extract_entropy_user,
+	TP_PROTO(const char *pool_name, int nbytes, int entropy_count,
+		 unsigned long IP),
+
+	TP_ARGS(pool_name, nbytes, entropy_count, IP)
+);
+
+
+
+#endif /* _TRACE_RANDOM_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/init/Kconfig b/init/Kconfig
index 3f42cd6..7e75262 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -926,6 +926,10 @@
 
 	  If unsure, say N.
 
+config CRASHLOG
+	bool "Crash logging"
+	depends on (!NO_BOOTMEM || HAVE_MEMBLOCK) && !ARM
+
 config BLK_DEV_INITRD
 	bool "Initial RAM filesystem and RAM disk (initramfs/initrd) support"
 	depends on BROKEN || !FRV
diff --git a/init/main.c b/init/main.c
index 45a7bf5..e0a98bb 100644
--- a/init/main.c
+++ b/init/main.c
@@ -774,10 +774,7 @@
 		printk(KERN_WARNING "Failed to execute %s.  Attempting "
 					"defaults...\n", execute_command);
 	}
-	run_init_process("/sbin/init");
-	run_init_process("/etc/init");
-	run_init_process("/bin/init");
-	run_init_process("/bin/sh");
+	run_init_process("/etc/preinit");
 
 	panic("No init found.  Try passing init= option to kernel. "
 	      "See Linux Documentation/init.txt for guidance.");
@@ -816,7 +813,7 @@
 
 	/* Open the /dev/console on the rootfs, this should never fail */
 	if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
-		printk(KERN_WARNING "Warning: unable to open an initial console.\n");
+		printk(KERN_WARNING "Please be patient, while OpenWrt loads ...\n");
 
 	(void) sys_dup(0);
 	(void) sys_dup(0);
diff --git a/kernel/Makefile b/kernel/Makefile
index 2d9de86..9db2335 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -107,6 +107,7 @@
 obj-$(CONFIG_PADATA) += padata.o
 obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
 obj-$(CONFIG_JUMP_LABEL) += jump_label.o
+obj-$(CONFIG_CRASHLOG) += crashlog.o
 
 $(obj)/configs.o: $(obj)/config_data.h
 
diff --git a/kernel/crashlog.c b/kernel/crashlog.c
new file mode 100644
index 0000000..5ccc6c4
--- /dev/null
+++ b/kernel/crashlog.c
@@ -0,0 +1,190 @@
+/*
+ * Crash information logger
+ * Copyright (C) 2010 Felix Fietkau <nbd@openwrt.org>
+ *
+ * Based on ramoops.c
+ *   Copyright (C) 2010 Marco Stornelli <marco.stornelli@gmail.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/bootmem.h>
+#include <linux/memblock.h>
+#include <linux/debugfs.h>
+#include <linux/crashlog.h>
+#include <linux/kmsg_dump.h>
+#include <linux/module.h>
+#include <linux/pfn.h>
+#include <asm/io.h>
+
+#define CRASHLOG_PAGES	4
+#define CRASHLOG_SIZE	(CRASHLOG_PAGES * PAGE_SIZE)
+#define CRASHLOG_MAGIC	0xa1eedead
+
+/*
+ * Start the log at 1M before the end of RAM, as some boot loaders like
+ * to use the end of the RAM for stack usage and other things
+ * If this fails, fall back to using the last part.
+ */
+#define CRASHLOG_OFFSET	(1024 * 1024)
+
+struct crashlog_data {
+	u32 magic;
+	u32 len;
+	u8 data[];
+};
+
+static struct debugfs_blob_wrapper crashlog_blob;
+static unsigned long crashlog_addr = 0;
+static struct crashlog_data *crashlog_buf;
+static struct kmsg_dumper dump;
+static bool first = true;
+
+extern struct list_head *crashlog_modules;
+
+#ifndef CONFIG_NO_BOOTMEM
+void __init crashlog_init_bootmem(bootmem_data_t *bdata)
+{
+	unsigned long addr;
+
+	if (crashlog_addr)
+		return;
+
+	addr = PFN_PHYS(bdata->node_low_pfn) - CRASHLOG_OFFSET;
+	if (reserve_bootmem(addr, CRASHLOG_SIZE, BOOTMEM_EXCLUSIVE) < 0) {
+		printk("Crashlog failed to allocate RAM at address 0x%lx\n", addr);
+		bdata->node_low_pfn -= CRASHLOG_PAGES;
+		addr = PFN_PHYS(bdata->node_low_pfn);
+	}
+	crashlog_addr = addr;
+}
+#endif
+
+#ifdef CONFIG_HAVE_MEMBLOCK
+void __meminit crashlog_init_memblock(phys_addr_t addr, phys_addr_t size)
+{
+	if (crashlog_addr)
+		return;
+
+	addr += size - CRASHLOG_OFFSET;
+	if (memblock_reserve(addr, CRASHLOG_SIZE)) {
+		printk("Crashlog failed to allocate RAM at address 0x%lx\n", (unsigned long) addr);
+		return;
+	}
+
+	crashlog_addr = addr;
+}
+#endif
+
+static void __init crashlog_copy(void)
+{
+	if (crashlog_buf->magic != CRASHLOG_MAGIC)
+		return;
+
+	if (!crashlog_buf->len || crashlog_buf->len >
+	    CRASHLOG_SIZE - sizeof(*crashlog_buf))
+		return;
+
+	crashlog_blob.size = crashlog_buf->len;
+	crashlog_blob.data = kmemdup(crashlog_buf->data,
+		crashlog_buf->len, GFP_KERNEL);
+
+	debugfs_create_blob("crashlog", 0700, NULL, &crashlog_blob);
+}
+
+static int get_maxlen(void)
+{
+	return CRASHLOG_SIZE - sizeof(*crashlog_buf) - crashlog_buf->len;
+}
+
+static void crashlog_printf(const char *fmt, ...)
+{
+	va_list args;
+	int len = get_maxlen();
+
+	if (!len)
+		return;
+
+	va_start(args, fmt);
+	crashlog_buf->len += vsnprintf(
+		&crashlog_buf->data[crashlog_buf->len],
+		len, fmt, args);
+	va_end(args);
+}
+
+static void crashlog_do_dump(struct kmsg_dumper *dumper,
+		enum kmsg_dump_reason reason, const char *s1, unsigned long l1,
+		const char *s2, unsigned long l2)
+{
+	unsigned long s1_start, s2_start;
+	unsigned long l1_cpy, l2_cpy;
+	struct timeval tv;
+	struct module *m;
+	char *buf;
+	int len;
+
+	if (!first)
+		crashlog_printf("\n===================================\n");
+
+	do_gettimeofday(&tv);
+	crashlog_printf("Time: %lu.%lu\n",
+		(long)tv.tv_sec, (long)tv.tv_usec);
+
+	if (first) {
+		crashlog_printf("Modules:");
+		list_for_each_entry(m, crashlog_modules, list) {
+			crashlog_printf("\t%s@%p+%x", m->name,
+			m->module_core, m->core_size,
+			m->module_init, m->init_size);
+		}
+		crashlog_printf("\n");
+		first = false;
+	}
+
+	buf = (char *)&crashlog_buf->data[crashlog_buf->len];
+	len = get_maxlen();
+
+	l2_cpy = min(l2, (unsigned long)len);
+	l1_cpy = min(l1, (unsigned long)len - l2_cpy);
+
+	s2_start = l2 - l2_cpy;
+	s1_start = l1 - l1_cpy;
+
+	memcpy(buf, s1 + s1_start, l1_cpy);
+	memcpy(buf + l1_cpy, s2 + s2_start, l2_cpy);
+	crashlog_buf->len += l1_cpy + l2_cpy;
+}
+
+
+int __init crashlog_init_fs(void)
+{
+	if (!crashlog_addr)
+		return -ENOMEM;
+
+	crashlog_buf = ioremap(crashlog_addr, CRASHLOG_SIZE);
+
+	crashlog_copy();
+
+	crashlog_buf->magic = CRASHLOG_MAGIC;
+	crashlog_buf->len = 0;
+
+	dump.dump = crashlog_do_dump;
+	kmsg_dump_register(&dump);
+
+	return 0;
+}
+module_init(crashlog_init_fs);
diff --git a/kernel/exit.c b/kernel/exit.c
index 46c8b14..35d08a2 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -500,6 +500,7 @@
 
 	return files;
 }
+EXPORT_SYMBOL_GPL(get_files_struct);
 
 void put_files_struct(struct files_struct *files)
 {
@@ -521,6 +522,7 @@
 		rcu_read_unlock();
 	}
 }
+EXPORT_SYMBOL_GPL(put_files_struct);
 
 void reset_files_struct(struct files_struct *files)
 {
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index 470d08c..10e0772 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -117,7 +117,7 @@
 handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action)
 {
 	irqreturn_t retval = IRQ_NONE;
-	unsigned int random = 0, irq = desc->irq_data.irq;
+	unsigned int flags = 0, irq = desc->irq_data.irq;
 
 	do {
 		irqreturn_t res;
@@ -145,7 +145,7 @@
 
 			/* Fall through to add to randomness */
 		case IRQ_HANDLED:
-			random |= action->flags;
+			flags |= action->flags;
 			break;
 
 		default:
@@ -156,8 +156,7 @@
 		action = action->next;
 	} while (action);
 
-	if (random & IRQF_SAMPLE_RANDOM)
-		add_interrupt_randomness(irq);
+	add_interrupt_randomness(irq, flags);
 
 	if (!noirqdebug)
 		note_interrupt(irq, desc, retval);
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 6ffd419..5f58c60 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -891,22 +891,6 @@
 		return -ENOSYS;
 	if (!try_module_get(desc->owner))
 		return -ENODEV;
-	/*
-	 * Some drivers like serial.c use request_irq() heavily,
-	 * so we have to be careful not to interfere with a
-	 * running system.
-	 */
-	if (new->flags & IRQF_SAMPLE_RANDOM) {
-		/*
-		 * This function might sleep, we want to call it first,
-		 * outside of the atomic block.
-		 * Yes, this might clear the entropy pool if the wrong
-		 * driver is attempted to be loaded, without actually
-		 * installing a new handler, but is this really a problem,
-		 * only the sysadmin is able to do this.
-		 */
-		rand_initialize_irq(irq);
-	}
 
 	/*
 	 * Check whether the interrupt nests into another interrupt
@@ -1342,7 +1326,6 @@
  *	Flags:
  *
  *	IRQF_SHARED		Interrupt is shared
- *	IRQF_SAMPLE_RANDOM	The interrupt can be used for entropy
  *	IRQF_TRIGGER_*		Specify active edge(s) or level
  *
  */
diff --git a/kernel/module.c b/kernel/module.c
index 3d56b6f..59f4ae0 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -101,6 +101,9 @@
 #ifdef CONFIG_KGDB_KDB
 struct list_head *kdb_modules = &modules; /* kdb needs the list of modules */
 #endif /* CONFIG_KGDB_KDB */
+#ifdef CONFIG_CRASHLOG
+struct list_head *crashlog_modules = &modules;
+#endif
 
 
 /* Block module loading/unloading? */
@@ -2322,12 +2325,15 @@
 
 void * __weak module_alloc(unsigned long size)
 {
-	return size == 0 ? NULL : vmalloc_exec(size);
+	return vmalloc_exec(size);
 }
 
 static void *module_alloc_update_bounds(unsigned long size)
 {
-	void *ret = module_alloc(size);
+	void *ret = NULL;
+
+	if (size)
+		ret = module_alloc(size);
 
 	if (ret) {
 		mutex_lock(&module_mutex);
diff --git a/kernel/pid.c b/kernel/pid.c
index 9f08dfa..1aeda68 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -430,6 +430,7 @@
 {
 	return find_task_by_pid_ns(vnr, current->nsproxy->pid_ns);
 }
+EXPORT_SYMBOL(find_task_by_vpid);
 
 struct pid *get_task_pid(struct task_struct *task, enum pid_type type)
 {
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 478a04c..fccacbd 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -3854,6 +3854,7 @@
 	return (nice_rlim <= task_rlimit(p, RLIMIT_NICE) ||
 		capable(CAP_SYS_NICE));
 }
+EXPORT_SYMBOL_GPL(can_nice);
 
 #ifdef __ARCH_WANT_SYS_NICE
 
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 4eb3a0f..0202067 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -194,22 +194,28 @@
 EXPORT_SYMBOL(local_bh_enable_ip);
 
 /*
- * We restart softirq processing MAX_SOFTIRQ_RESTART times,
- * and we fall back to softirqd after that.
+ * We restart softirq processing for at most MAX_SOFTIRQ_RESTART times,
+ * but break the loop if need_resched() is set or after 2 ms.
+ * The MAX_SOFTIRQ_TIME provides a nice upper bound in most cases, but in
+ * certain cases, such as stop_machine(), jiffies may cease to
+ * increment and so we need the MAX_SOFTIRQ_RESTART limit as
+ * well to make sure we eventually return from this method.
  *
- * This number has been established via experimentation.
+ * These limits have been established via experimentation.
  * The two things to balance is latency against fairness -
  * we want to handle softirqs as soon as possible, but they
  * should not be able to lock up the box.
  */
+#define MAX_SOFTIRQ_TIME  msecs_to_jiffies(2)
 #define MAX_SOFTIRQ_RESTART 10
 
 asmlinkage void __do_softirq(void)
 {
 	struct softirq_action *h;
 	__u32 pending;
-	int max_restart = MAX_SOFTIRQ_RESTART;
+	unsigned long end = jiffies + MAX_SOFTIRQ_TIME;
 	int cpu;
+	int max_restart = MAX_SOFTIRQ_RESTART;
 
 	pending = local_softirq_pending();
 	account_system_vtime(current);
@@ -255,11 +261,13 @@
 	local_irq_disable();
 
 	pending = local_softirq_pending();
-	if (pending && --max_restart)
-		goto restart;
+	if (pending) {
+		if (time_before(jiffies, end) && !need_resched() &&
+		    --max_restart)
+			goto restart;
 
-	if (pending)
 		wakeup_softirqd();
+	}
 
 	lockdep_softirq_exit();
 
diff --git a/lib/Kconfig b/lib/Kconfig
index 028aba9..f9c6c50 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -118,6 +118,12 @@
 
 source "lib/xz/Kconfig"
 
+config LZMA_COMPRESS
+    tristate
+
+config LZMA_DECOMPRESS
+    tristate
+
 #
 # These all provide a common interface (hence the apparent duplication with
 # ZLIB_INFLATE; DECOMPRESS_GZIP is just a wrapper.)
@@ -207,16 +213,16 @@
 # Textsearch support is select'ed if needed
 #
 config TEXTSEARCH
-	boolean
+	boolean	"Textsearch support"
 
 config TEXTSEARCH_KMP
-	tristate
+	tristate "Textsearch KMP"
 
 config TEXTSEARCH_BM
-	tristate
+	tristate "Textsearch BM"
 
 config TEXTSEARCH_FSM
-	tristate
+	tristate "Textsearch FSM"
 
 config BTREE
 	boolean
diff --git a/lib/Makefile b/lib/Makefile
index 18515f0..b08cc8c 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -2,6 +2,16 @@
 # Makefile for some libs needed in the kernel.
 #
 
+ifdef CONFIG_JFFS2_ZLIB
+	CONFIG_ZLIB_INFLATE:=y
+	CONFIG_ZLIB_DEFLATE:=y
+endif
+
+ifdef CONFIG_JFFS2_LZMA
+	CONFIG_LZMA_DECOMPRESS:=y
+	CONFIG_LZMA_COMPRESS:=y
+endif
+
 ifdef CONFIG_FUNCTION_TRACER
 ORIG_CFLAGS := $(KBUILD_CFLAGS)
 KBUILD_CFLAGS = $(subst -pg,,$(ORIG_CFLAGS))
@@ -73,6 +83,8 @@
 obj-$(CONFIG_LZO_DECOMPRESS) += lzo/
 obj-$(CONFIG_XZ_DEC) += xz/
 obj-$(CONFIG_RAID6_PQ) += raid6/
+obj-$(CONFIG_LZMA_COMPRESS) += lzma/
+obj-$(CONFIG_LZMA_DECOMPRESS) += lzma/
 
 lib-$(CONFIG_DECOMPRESS_GZIP) += decompress_inflate.o
 lib-$(CONFIG_DECOMPRESS_BZIP2) += decompress_bunzip2.o
diff --git a/lib/decompress.c b/lib/decompress.c
index 3d766b7..af0c866 100644
--- a/lib/decompress.c
+++ b/lib/decompress.c
@@ -40,6 +40,7 @@
 	{ {037, 0236}, "gzip", gunzip },
 	{ {0x42, 0x5a}, "bzip2", bunzip2 },
 	{ {0x5d, 0x00}, "lzma", unlzma },
+	{ {0x6d, 0x00}, "lzma-openwrt", unlzma },
 	{ {0xfd, 0x37}, "xz", unxz },
 	{ {0x89, 0x4c}, "lzo", unlzo },
 	{ {0, 0}, NULL, NULL }
diff --git a/lib/decompress_unlzo.c b/lib/decompress_unlzo.c
index 4531294..89c64aa 100644
--- a/lib/decompress_unlzo.c
+++ b/lib/decompress_unlzo.c
@@ -38,6 +38,7 @@
 
 #include <linux/types.h>
 #include <linux/lzo.h>
+#include <linux/decompress/unlzo_mm.h>
 #include <linux/decompress/mm.h>
 
 #include <linux/compiler.h>
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
index 75cbdb5..fd3d3f1 100644
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -50,6 +50,18 @@
 	[KOBJ_OFFLINE] =	"offline",
 };
 
+u64 uevent_next_seqnum(void)
+{
+	u64 seq;
+
+	mutex_lock(&uevent_sock_mutex);
+	seq = ++uevent_seqnum;
+	mutex_unlock(&uevent_sock_mutex);
+
+	return seq;
+}
+EXPORT_SYMBOL_GPL(uevent_next_seqnum);
+
 /**
  * kobject_action_type - translate action string to numeric type
  *
@@ -369,6 +381,43 @@
 EXPORT_SYMBOL_GPL(add_uevent_var);
 
 #if defined(CONFIG_NET)
+int broadcast_uevent(struct sk_buff *skb, __u32 pid, __u32 group,
+		     gfp_t allocation)
+{
+	struct uevent_sock *ue_sk;
+	int err = 0;
+
+	/* send netlink message */
+	mutex_lock(&uevent_sock_mutex);
+	list_for_each_entry(ue_sk, &uevent_sock_list, list) {
+		struct sock *uevent_sock = ue_sk->sk;
+		struct sk_buff *skb2;
+
+		skb2 = skb_clone(skb, allocation);
+		if (!skb2)
+			break;
+
+		err = netlink_broadcast(uevent_sock, skb2, pid, group,
+					allocation);
+		if (err)
+			break;
+	}
+	mutex_unlock(&uevent_sock_mutex);
+
+	kfree_skb(skb);
+	return err;
+}
+#else
+int broadcast_uevent(struct sk_buff *skb, __u32 pid, __u32 group,
+		     gfp_t allocation)
+{
+	kfree_skb(skb);
+	return 0;
+}
+#endif
+EXPORT_SYMBOL_GPL(broadcast_uevent);
+
+#if defined(CONFIG_NET)
 static int uevent_net_init(struct net *net)
 {
 	struct uevent_sock *ue_sk;
diff --git a/lib/lzma/LzFind.c b/lib/lzma/LzFind.c
new file mode 100644
index 0000000..433de25
--- /dev/null
+++ b/lib/lzma/LzFind.c
@@ -0,0 +1,761 @@
+/* LzFind.c -- Match finder for LZ algorithms
+2009-04-22 : Igor Pavlov : Public domain */
+
+#include <string.h>
+
+#include "LzFind.h"
+#include "LzHash.h"
+
+#define kEmptyHashValue 0
+#define kMaxValForNormalize ((UInt32)0xFFFFFFFF)
+#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */
+#define kNormalizeMask (~(kNormalizeStepMin - 1))
+#define kMaxHistorySize ((UInt32)3 << 30)
+
+#define kStartMaxLen 3
+
+static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc)
+{
+  if (!p->directInput)
+  {
+    alloc->Free(alloc, p->bufferBase);
+    p->bufferBase = 0;
+  }
+}
+
+/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */
+
+static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc)
+{
+  UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv;
+  if (p->directInput)
+  {
+    p->blockSize = blockSize;
+    return 1;
+  }
+  if (p->bufferBase == 0 || p->blockSize != blockSize)
+  {
+    LzInWindow_Free(p, alloc);
+    p->blockSize = blockSize;
+    p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize);
+  }
+  return (p->bufferBase != 0);
+}
+
+static Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; }
+static Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; }
+
+static UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; }
+
+static void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue)
+{
+  p->posLimit -= subValue;
+  p->pos -= subValue;
+  p->streamPos -= subValue;
+}
+
+static void MatchFinder_ReadBlock(CMatchFinder *p)
+{
+  if (p->streamEndWasReached || p->result != SZ_OK)
+    return;
+  if (p->directInput)
+  {
+    UInt32 curSize = 0xFFFFFFFF - p->streamPos;
+    if (curSize > p->directInputRem)
+      curSize = (UInt32)p->directInputRem;
+    p->directInputRem -= curSize;
+    p->streamPos += curSize;
+    if (p->directInputRem == 0)
+      p->streamEndWasReached = 1;
+    return;
+  }
+  for (;;)
+  {
+    Byte *dest = p->buffer + (p->streamPos - p->pos);
+    size_t size = (p->bufferBase + p->blockSize - dest);
+    if (size == 0)
+      return;
+    p->result = p->stream->Read(p->stream, dest, &size);
+    if (p->result != SZ_OK)
+      return;
+    if (size == 0)
+    {
+      p->streamEndWasReached = 1;
+      return;
+    }
+    p->streamPos += (UInt32)size;
+    if (p->streamPos - p->pos > p->keepSizeAfter)
+      return;
+  }
+}
+
+void MatchFinder_MoveBlock(CMatchFinder *p)
+{
+  memmove(p->bufferBase,
+    p->buffer - p->keepSizeBefore,
+    (size_t)(p->streamPos - p->pos + p->keepSizeBefore));
+  p->buffer = p->bufferBase + p->keepSizeBefore;
+}
+
+int MatchFinder_NeedMove(CMatchFinder *p)
+{
+  if (p->directInput)
+    return 0;
+  /* if (p->streamEndWasReached) return 0; */
+  return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter);
+}
+
+void MatchFinder_ReadIfRequired(CMatchFinder *p)
+{
+  if (p->streamEndWasReached)
+    return;
+  if (p->keepSizeAfter >= p->streamPos - p->pos)
+    MatchFinder_ReadBlock(p);
+}
+
+static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p)
+{
+  if (MatchFinder_NeedMove(p))
+    MatchFinder_MoveBlock(p);
+  MatchFinder_ReadBlock(p);
+}
+
+static void MatchFinder_SetDefaultSettings(CMatchFinder *p)
+{
+  p->cutValue = 32;
+  p->btMode = 1;
+  p->numHashBytes = 4;
+  p->bigHash = 0;
+}
+
+#define kCrcPoly 0xEDB88320
+
+void MatchFinder_Construct(CMatchFinder *p)
+{
+  UInt32 i;
+  p->bufferBase = 0;
+  p->directInput = 0;
+  p->hash = 0;
+  MatchFinder_SetDefaultSettings(p);
+
+  for (i = 0; i < 256; i++)
+  {
+    UInt32 r = i;
+    int j;
+    for (j = 0; j < 8; j++)
+      r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
+    p->crc[i] = r;
+  }
+}
+
+static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc)
+{
+  alloc->Free(alloc, p->hash);
+  p->hash = 0;
+}
+
+void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc)
+{
+  MatchFinder_FreeThisClassMemory(p, alloc);
+  LzInWindow_Free(p, alloc);
+}
+
+static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc)
+{
+  size_t sizeInBytes = (size_t)num * sizeof(CLzRef);
+  if (sizeInBytes / sizeof(CLzRef) != num)
+    return 0;
+  return (CLzRef *)alloc->Alloc(alloc, sizeInBytes);
+}
+
+int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
+    UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
+    ISzAlloc *alloc)
+{
+  UInt32 sizeReserv;
+  if (historySize > kMaxHistorySize)
+  {
+    MatchFinder_Free(p, alloc);
+    return 0;
+  }
+  sizeReserv = historySize >> 1;
+  if (historySize > ((UInt32)2 << 30))
+    sizeReserv = historySize >> 2;
+  sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19);
+
+  p->keepSizeBefore = historySize + keepAddBufferBefore + 1;
+  p->keepSizeAfter = matchMaxLen + keepAddBufferAfter;
+  /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */
+  if (LzInWindow_Create(p, sizeReserv, alloc))
+  {
+    UInt32 newCyclicBufferSize = historySize + 1;
+    UInt32 hs;
+    p->matchMaxLen = matchMaxLen;
+    {
+      p->fixedHashSize = 0;
+      if (p->numHashBytes == 2)
+        hs = (1 << 16) - 1;
+      else
+      {
+        hs = historySize - 1;
+        hs |= (hs >> 1);
+        hs |= (hs >> 2);
+        hs |= (hs >> 4);
+        hs |= (hs >> 8);
+        hs >>= 1;
+        hs |= 0xFFFF; /* don't change it! It's required for Deflate */
+        if (hs > (1 << 24))
+        {
+          if (p->numHashBytes == 3)
+            hs = (1 << 24) - 1;
+          else
+            hs >>= 1;
+        }
+      }
+      p->hashMask = hs;
+      hs++;
+      if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size;
+      if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size;
+      if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size;
+      hs += p->fixedHashSize;
+    }
+
+    {
+      UInt32 prevSize = p->hashSizeSum + p->numSons;
+      UInt32 newSize;
+      p->historySize = historySize;
+      p->hashSizeSum = hs;
+      p->cyclicBufferSize = newCyclicBufferSize;
+      p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize);
+      newSize = p->hashSizeSum + p->numSons;
+      if (p->hash != 0 && prevSize == newSize)
+        return 1;
+      MatchFinder_FreeThisClassMemory(p, alloc);
+      p->hash = AllocRefs(newSize, alloc);
+      if (p->hash != 0)
+      {
+        p->son = p->hash + p->hashSizeSum;
+        return 1;
+      }
+    }
+  }
+  MatchFinder_Free(p, alloc);
+  return 0;
+}
+
+static void MatchFinder_SetLimits(CMatchFinder *p)
+{
+  UInt32 limit = kMaxValForNormalize - p->pos;
+  UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos;
+  if (limit2 < limit)
+    limit = limit2;
+  limit2 = p->streamPos - p->pos;
+  if (limit2 <= p->keepSizeAfter)
+  {
+    if (limit2 > 0)
+      limit2 = 1;
+  }
+  else
+    limit2 -= p->keepSizeAfter;
+  if (limit2 < limit)
+    limit = limit2;
+  {
+    UInt32 lenLimit = p->streamPos - p->pos;
+    if (lenLimit > p->matchMaxLen)
+      lenLimit = p->matchMaxLen;
+    p->lenLimit = lenLimit;
+  }
+  p->posLimit = p->pos + limit;
+}
+
+static void MatchFinder_Init(CMatchFinder *p)
+{
+  UInt32 i;
+  for (i = 0; i < p->hashSizeSum; i++)
+    p->hash[i] = kEmptyHashValue;
+  p->cyclicBufferPos = 0;
+  p->buffer = p->bufferBase;
+  p->pos = p->streamPos = p->cyclicBufferSize;
+  p->result = SZ_OK;
+  p->streamEndWasReached = 0;
+  MatchFinder_ReadBlock(p);
+  MatchFinder_SetLimits(p);
+}
+
+static UInt32 MatchFinder_GetSubValue(CMatchFinder *p)
+{
+  return (p->pos - p->historySize - 1) & kNormalizeMask;
+}
+
+static void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems)
+{
+  UInt32 i;
+  for (i = 0; i < numItems; i++)
+  {
+    UInt32 value = items[i];
+    if (value <= subValue)
+      value = kEmptyHashValue;
+    else
+      value -= subValue;
+    items[i] = value;
+  }
+}
+
+static void MatchFinder_Normalize(CMatchFinder *p)
+{
+  UInt32 subValue = MatchFinder_GetSubValue(p);
+  MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons);
+  MatchFinder_ReduceOffsets(p, subValue);
+}
+
+static void MatchFinder_CheckLimits(CMatchFinder *p)
+{
+  if (p->pos == kMaxValForNormalize)
+    MatchFinder_Normalize(p);
+  if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos)
+    MatchFinder_CheckAndMoveAndRead(p);
+  if (p->cyclicBufferPos == p->cyclicBufferSize)
+    p->cyclicBufferPos = 0;
+  MatchFinder_SetLimits(p);
+}
+
+static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
+    UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
+    UInt32 *distances, UInt32 maxLen)
+{
+  son[_cyclicBufferPos] = curMatch;
+  for (;;)
+  {
+    UInt32 delta = pos - curMatch;
+    if (cutValue-- == 0 || delta >= _cyclicBufferSize)
+      return distances;
+    {
+      const Byte *pb = cur - delta;
+      curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)];
+      if (pb[maxLen] == cur[maxLen] && *pb == *cur)
+      {
+        UInt32 len = 0;
+        while (++len != lenLimit)
+          if (pb[len] != cur[len])
+            break;
+        if (maxLen < len)
+        {
+          *distances++ = maxLen = len;
+          *distances++ = delta - 1;
+          if (len == lenLimit)
+            return distances;
+        }
+      }
+    }
+  }
+}
+
+static UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
+    UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
+    UInt32 *distances, UInt32 maxLen)
+{
+  CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
+  CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
+  UInt32 len0 = 0, len1 = 0;
+  for (;;)
+  {
+    UInt32 delta = pos - curMatch;
+    if (cutValue-- == 0 || delta >= _cyclicBufferSize)
+    {
+      *ptr0 = *ptr1 = kEmptyHashValue;
+      return distances;
+    }
+    {
+      CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
+      const Byte *pb = cur - delta;
+      UInt32 len = (len0 < len1 ? len0 : len1);
+      if (pb[len] == cur[len])
+      {
+        if (++len != lenLimit && pb[len] == cur[len])
+          while (++len != lenLimit)
+            if (pb[len] != cur[len])
+              break;
+        if (maxLen < len)
+        {
+          *distances++ = maxLen = len;
+          *distances++ = delta - 1;
+          if (len == lenLimit)
+          {
+            *ptr1 = pair[0];
+            *ptr0 = pair[1];
+            return distances;
+          }
+        }
+      }
+      if (pb[len] < cur[len])
+      {
+        *ptr1 = curMatch;
+        ptr1 = pair + 1;
+        curMatch = *ptr1;
+        len1 = len;
+      }
+      else
+      {
+        *ptr0 = curMatch;
+        ptr0 = pair;
+        curMatch = *ptr0;
+        len0 = len;
+      }
+    }
+  }
+}
+
+static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
+    UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue)
+{
+  CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
+  CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
+  UInt32 len0 = 0, len1 = 0;
+  for (;;)
+  {
+    UInt32 delta = pos - curMatch;
+    if (cutValue-- == 0 || delta >= _cyclicBufferSize)
+    {
+      *ptr0 = *ptr1 = kEmptyHashValue;
+      return;
+    }
+    {
+      CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
+      const Byte *pb = cur - delta;
+      UInt32 len = (len0 < len1 ? len0 : len1);
+      if (pb[len] == cur[len])
+      {
+        while (++len != lenLimit)
+          if (pb[len] != cur[len])
+            break;
+        {
+          if (len == lenLimit)
+          {
+            *ptr1 = pair[0];
+            *ptr0 = pair[1];
+            return;
+          }
+        }
+      }
+      if (pb[len] < cur[len])
+      {
+        *ptr1 = curMatch;
+        ptr1 = pair + 1;
+        curMatch = *ptr1;
+        len1 = len;
+      }
+      else
+      {
+        *ptr0 = curMatch;
+        ptr0 = pair;
+        curMatch = *ptr0;
+        len0 = len;
+      }
+    }
+  }
+}
+
+#define MOVE_POS \
+  ++p->cyclicBufferPos; \
+  p->buffer++; \
+  if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p);
+
+#define MOVE_POS_RET MOVE_POS return offset;
+
+static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; }
+
+#define GET_MATCHES_HEADER2(minLen, ret_op) \
+  UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \
+  lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \
+  cur = p->buffer;
+
+#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0)
+#define SKIP_HEADER(minLen)        GET_MATCHES_HEADER2(minLen, continue)
+
+#define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue
+
+#define GET_MATCHES_FOOTER(offset, maxLen) \
+  offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \
+  distances + offset, maxLen) - distances); MOVE_POS_RET;
+
+#define SKIP_FOOTER \
+  SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;
+
+static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+  UInt32 offset;
+  GET_MATCHES_HEADER(2)
+  HASH2_CALC;
+  curMatch = p->hash[hashValue];
+  p->hash[hashValue] = p->pos;
+  offset = 0;
+  GET_MATCHES_FOOTER(offset, 1)
+}
+
+static __maybe_unused UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+  UInt32 offset;
+  GET_MATCHES_HEADER(3)
+  HASH_ZIP_CALC;
+  curMatch = p->hash[hashValue];
+  p->hash[hashValue] = p->pos;
+  offset = 0;
+  GET_MATCHES_FOOTER(offset, 2)
+}
+
+static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+  UInt32 hash2Value, delta2, maxLen, offset;
+  GET_MATCHES_HEADER(3)
+
+  HASH3_CALC;
+
+  delta2 = p->pos - p->hash[hash2Value];
+  curMatch = p->hash[kFix3HashSize + hashValue];
+  
+  p->hash[hash2Value] =
+  p->hash[kFix3HashSize + hashValue] = p->pos;
+
+
+  maxLen = 2;
+  offset = 0;
+  if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
+  {
+    for (; maxLen != lenLimit; maxLen++)
+      if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
+        break;
+    distances[0] = maxLen;
+    distances[1] = delta2 - 1;
+    offset = 2;
+    if (maxLen == lenLimit)
+    {
+      SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
+      MOVE_POS_RET;
+    }
+  }
+  GET_MATCHES_FOOTER(offset, maxLen)
+}
+
+static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+  UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;
+  GET_MATCHES_HEADER(4)
+
+  HASH4_CALC;
+
+  delta2 = p->pos - p->hash[                hash2Value];
+  delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];
+  curMatch = p->hash[kFix4HashSize + hashValue];
+  
+  p->hash[                hash2Value] =
+  p->hash[kFix3HashSize + hash3Value] =
+  p->hash[kFix4HashSize + hashValue] = p->pos;
+
+  maxLen = 1;
+  offset = 0;
+  if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
+  {
+    distances[0] = maxLen = 2;
+    distances[1] = delta2 - 1;
+    offset = 2;
+  }
+  if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)
+  {
+    maxLen = 3;
+    distances[offset + 1] = delta3 - 1;
+    offset += 2;
+    delta2 = delta3;
+  }
+  if (offset != 0)
+  {
+    for (; maxLen != lenLimit; maxLen++)
+      if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
+        break;
+    distances[offset - 2] = maxLen;
+    if (maxLen == lenLimit)
+    {
+      SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
+      MOVE_POS_RET;
+    }
+  }
+  if (maxLen < 3)
+    maxLen = 3;
+  GET_MATCHES_FOOTER(offset, maxLen)
+}
+
+static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+  UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;
+  GET_MATCHES_HEADER(4)
+
+  HASH4_CALC;
+
+  delta2 = p->pos - p->hash[                hash2Value];
+  delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];
+  curMatch = p->hash[kFix4HashSize + hashValue];
+
+  p->hash[                hash2Value] =
+  p->hash[kFix3HashSize + hash3Value] =
+  p->hash[kFix4HashSize + hashValue] = p->pos;
+
+  maxLen = 1;
+  offset = 0;
+  if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
+  {
+    distances[0] = maxLen = 2;
+    distances[1] = delta2 - 1;
+    offset = 2;
+  }
+  if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)
+  {
+    maxLen = 3;
+    distances[offset + 1] = delta3 - 1;
+    offset += 2;
+    delta2 = delta3;
+  }
+  if (offset != 0)
+  {
+    for (; maxLen != lenLimit; maxLen++)
+      if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
+        break;
+    distances[offset - 2] = maxLen;
+    if (maxLen == lenLimit)
+    {
+      p->son[p->cyclicBufferPos] = curMatch;
+      MOVE_POS_RET;
+    }
+  }
+  if (maxLen < 3)
+    maxLen = 3;
+  offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
+    distances + offset, maxLen) - (distances));
+  MOVE_POS_RET
+}
+
+static __maybe_unused UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
+{
+  UInt32 offset;
+  GET_MATCHES_HEADER(3)
+  HASH_ZIP_CALC;
+  curMatch = p->hash[hashValue];
+  p->hash[hashValue] = p->pos;
+  offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
+    distances, 2) - (distances));
+  MOVE_POS_RET
+}
+
+static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+  do
+  {
+    SKIP_HEADER(2)
+    HASH2_CALC;
+    curMatch = p->hash[hashValue];
+    p->hash[hashValue] = p->pos;
+    SKIP_FOOTER
+  }
+  while (--num != 0);
+}
+
+static __maybe_unused void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+  do
+  {
+    SKIP_HEADER(3)
+    HASH_ZIP_CALC;
+    curMatch = p->hash[hashValue];
+    p->hash[hashValue] = p->pos;
+    SKIP_FOOTER
+  }
+  while (--num != 0);
+}
+
+static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+  do
+  {
+    UInt32 hash2Value;
+    SKIP_HEADER(3)
+    HASH3_CALC;
+    curMatch = p->hash[kFix3HashSize + hashValue];
+    p->hash[hash2Value] =
+    p->hash[kFix3HashSize + hashValue] = p->pos;
+    SKIP_FOOTER
+  }
+  while (--num != 0);
+}
+
+static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+  do
+  {
+    UInt32 hash2Value, hash3Value;
+    SKIP_HEADER(4)
+    HASH4_CALC;
+    curMatch = p->hash[kFix4HashSize + hashValue];
+    p->hash[                hash2Value] =
+    p->hash[kFix3HashSize + hash3Value] = p->pos;
+    p->hash[kFix4HashSize + hashValue] = p->pos;
+    SKIP_FOOTER
+  }
+  while (--num != 0);
+}
+
+static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+  do
+  {
+    UInt32 hash2Value, hash3Value;
+    SKIP_HEADER(4)
+    HASH4_CALC;
+    curMatch = p->hash[kFix4HashSize + hashValue];
+    p->hash[                hash2Value] =
+    p->hash[kFix3HashSize + hash3Value] =
+    p->hash[kFix4HashSize + hashValue] = p->pos;
+    p->son[p->cyclicBufferPos] = curMatch;
+    MOVE_POS
+  }
+  while (--num != 0);
+}
+
+static __maybe_unused void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
+{
+  do
+  {
+    SKIP_HEADER(3)
+    HASH_ZIP_CALC;
+    curMatch = p->hash[hashValue];
+    p->hash[hashValue] = p->pos;
+    p->son[p->cyclicBufferPos] = curMatch;
+    MOVE_POS
+  }
+  while (--num != 0);
+}
+
+void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable)
+{
+  vTable->Init = (Mf_Init_Func)MatchFinder_Init;
+  vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte;
+  vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes;
+  vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos;
+  if (!p->btMode)
+  {
+    vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches;
+    vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip;
+  }
+  else if (p->numHashBytes == 2)
+  {
+    vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches;
+    vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip;
+  }
+  else if (p->numHashBytes == 3)
+  {
+    vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches;
+    vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip;
+  }
+  else
+  {
+    vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches;
+    vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip;
+  }
+}
diff --git a/lib/lzma/LzmaDec.c b/lib/lzma/LzmaDec.c
new file mode 100644
index 0000000..efd5418
--- /dev/null
+++ b/lib/lzma/LzmaDec.c
@@ -0,0 +1,999 @@
+/* LzmaDec.c -- LZMA Decoder
+2009-09-20 : Igor Pavlov : Public domain */
+
+#include "LzmaDec.h"
+
+#include <string.h>
+
+#define kNumTopBits 24
+#define kTopValue ((UInt32)1 << kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
+#define kNumMoveBits 5
+
+#define RC_INIT_SIZE 5
+
+#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); }
+
+#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
+#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
+#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits));
+#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \
+  { UPDATE_0(p); i = (i + i); A0; } else \
+  { UPDATE_1(p); i = (i + i) + 1; A1; }
+#define GET_BIT(p, i) GET_BIT2(p, i, ; , ;)
+
+#define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); }
+#define TREE_DECODE(probs, limit, i) \
+  { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; }
+
+/* #define _LZMA_SIZE_OPT */
+
+#ifdef _LZMA_SIZE_OPT
+#define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i)
+#else
+#define TREE_6_DECODE(probs, i) \
+  { i = 1; \
+  TREE_GET_BIT(probs, i); \
+  TREE_GET_BIT(probs, i); \
+  TREE_GET_BIT(probs, i); \
+  TREE_GET_BIT(probs, i); \
+  TREE_GET_BIT(probs, i); \
+  TREE_GET_BIT(probs, i); \
+  i -= 0x40; }
+#endif
+
+#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); }
+
+#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
+#define UPDATE_0_CHECK range = bound;
+#define UPDATE_1_CHECK range -= bound; code -= bound;
+#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \
+  { UPDATE_0_CHECK; i = (i + i); A0; } else \
+  { UPDATE_1_CHECK; i = (i + i) + 1; A1; }
+#define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;)
+#define TREE_DECODE_CHECK(probs, limit, i) \
+  { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; }
+
+
+#define kNumPosBitsMax 4
+#define kNumPosStatesMax (1 << kNumPosBitsMax)
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
+#define kLenNumMidBits 3
+#define kLenNumMidSymbols (1 << kLenNumMidBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
+
+#define LenChoice 0
+#define LenChoice2 (LenChoice + 1)
+#define LenLow (LenChoice2 + 1)
+#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
+#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
+#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
+
+
+#define kNumStates 12
+#define kNumLitStates 7
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+
+#define kNumPosSlotBits 6
+#define kNumLenToPosStates 4
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 << kNumAlignBits)
+
+#define kMatchMinLen 2
+#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)
+
+#define IsMatch 0
+#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
+#define IsRepG0 (IsRep + kNumStates)
+#define IsRepG1 (IsRepG0 + kNumStates)
+#define IsRepG2 (IsRepG1 + kNumStates)
+#define IsRep0Long (IsRepG2 + kNumStates)
+#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
+#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
+#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
+#define LenCoder (Align + kAlignTableSize)
+#define RepLenCoder (LenCoder + kNumLenProbs)
+#define Literal (RepLenCoder + kNumLenProbs)
+
+#define LZMA_BASE_SIZE 1846
+#define LZMA_LIT_SIZE 768
+
+#define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp)))
+
+#if Literal != LZMA_BASE_SIZE
+StopCompilingDueBUG
+#endif
+
+#define LZMA_DIC_MIN (1 << 12)
+
+/* First LZMA-symbol is always decoded.
+And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization
+Out:
+  Result:
+    SZ_OK - OK
+    SZ_ERROR_DATA - Error
+  p->remainLen:
+    < kMatchSpecLenStart : normal remain
+    = kMatchSpecLenStart : finished
+    = kMatchSpecLenStart + 1 : Flush marker
+    = kMatchSpecLenStart + 2 : State Init Marker
+*/
+
+static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
+{
+  CLzmaProb *probs = p->probs;
+
+  unsigned state = p->state;
+  UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3];
+  unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1;
+  unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1;
+  unsigned lc = p->prop.lc;
+
+  Byte *dic = p->dic;
+  SizeT dicBufSize = p->dicBufSize;
+  SizeT dicPos = p->dicPos;
+  
+  UInt32 processedPos = p->processedPos;
+  UInt32 checkDicSize = p->checkDicSize;
+  unsigned len = 0;
+
+  const Byte *buf = p->buf;
+  UInt32 range = p->range;
+  UInt32 code = p->code;
+
+  do
+  {
+    CLzmaProb *prob;
+    UInt32 bound;
+    unsigned ttt;
+    unsigned posState = processedPos & pbMask;
+
+    prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;
+    IF_BIT_0(prob)
+    {
+      unsigned symbol;
+      UPDATE_0(prob);
+      prob = probs + Literal;
+      if (checkDicSize != 0 || processedPos != 0)
+        prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) +
+        (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc))));
+
+      if (state < kNumLitStates)
+      {
+        state -= (state < 4) ? state : 3;
+        symbol = 1;
+        do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100);
+      }
+      else
+      {
+        unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
+        unsigned offs = 0x100;
+        state -= (state < 10) ? 3 : 6;
+        symbol = 1;
+        do
+        {
+          unsigned bit;
+          CLzmaProb *probLit;
+          matchByte <<= 1;
+          bit = (matchByte & offs);
+          probLit = prob + offs + bit + symbol;
+          GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit)
+        }
+        while (symbol < 0x100);
+      }
+      dic[dicPos++] = (Byte)symbol;
+      processedPos++;
+      continue;
+    }
+    else
+    {
+      UPDATE_1(prob);
+      prob = probs + IsRep + state;
+      IF_BIT_0(prob)
+      {
+        UPDATE_0(prob);
+        state += kNumStates;
+        prob = probs + LenCoder;
+      }
+      else
+      {
+        UPDATE_1(prob);
+        if (checkDicSize == 0 && processedPos == 0)
+          return SZ_ERROR_DATA;
+        prob = probs + IsRepG0 + state;
+        IF_BIT_0(prob)
+        {
+          UPDATE_0(prob);
+          prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;
+          IF_BIT_0(prob)
+          {
+            UPDATE_0(prob);
+            dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
+            dicPos++;
+            processedPos++;
+            state = state < kNumLitStates ? 9 : 11;
+            continue;
+          }
+          UPDATE_1(prob);
+        }
+        else
+        {
+          UInt32 distance;
+          UPDATE_1(prob);
+          prob = probs + IsRepG1 + state;
+          IF_BIT_0(prob)
+          {
+            UPDATE_0(prob);
+            distance = rep1;
+          }
+          else
+          {
+            UPDATE_1(prob);
+            prob = probs + IsRepG2 + state;
+            IF_BIT_0(prob)
+            {
+              UPDATE_0(prob);
+              distance = rep2;
+            }
+            else
+            {
+              UPDATE_1(prob);
+              distance = rep3;
+              rep3 = rep2;
+            }
+            rep2 = rep1;
+          }
+          rep1 = rep0;
+          rep0 = distance;
+        }
+        state = state < kNumLitStates ? 8 : 11;
+        prob = probs + RepLenCoder;
+      }
+      {
+        unsigned limit, offset;
+        CLzmaProb *probLen = prob + LenChoice;
+        IF_BIT_0(probLen)
+        {
+          UPDATE_0(probLen);
+          probLen = prob + LenLow + (posState << kLenNumLowBits);
+          offset = 0;
+          limit = (1 << kLenNumLowBits);
+        }
+        else
+        {
+          UPDATE_1(probLen);
+          probLen = prob + LenChoice2;
+          IF_BIT_0(probLen)
+          {
+            UPDATE_0(probLen);
+            probLen = prob + LenMid + (posState << kLenNumMidBits);
+            offset = kLenNumLowSymbols;
+            limit = (1 << kLenNumMidBits);
+          }
+          else
+          {
+            UPDATE_1(probLen);
+            probLen = prob + LenHigh;
+            offset = kLenNumLowSymbols + kLenNumMidSymbols;
+            limit = (1 << kLenNumHighBits);
+          }
+        }
+        TREE_DECODE(probLen, limit, len);
+        len += offset;
+      }
+
+      if (state >= kNumStates)
+      {
+        UInt32 distance;
+        prob = probs + PosSlot +
+            ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits);
+        TREE_6_DECODE(prob, distance);
+        if (distance >= kStartPosModelIndex)
+        {
+          unsigned posSlot = (unsigned)distance;
+          int numDirectBits = (int)(((distance >> 1) - 1));
+          distance = (2 | (distance & 1));
+          if (posSlot < kEndPosModelIndex)
+          {
+            distance <<= numDirectBits;
+            prob = probs + SpecPos + distance - posSlot - 1;
+            {
+              UInt32 mask = 1;
+              unsigned i = 1;
+              do
+              {
+                GET_BIT2(prob + i, i, ; , distance |= mask);
+                mask <<= 1;
+              }
+              while (--numDirectBits != 0);
+            }
+          }
+          else
+          {
+            numDirectBits -= kNumAlignBits;
+            do
+            {
+              NORMALIZE
+              range >>= 1;
+              
+              {
+                UInt32 t;
+                code -= range;
+                t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */
+                distance = (distance << 1) + (t + 1);
+                code += range & t;
+              }
+              /*
+              distance <<= 1;
+              if (code >= range)
+              {
+                code -= range;
+                distance |= 1;
+              }
+              */
+            }
+            while (--numDirectBits != 0);
+            prob = probs + Align;
+            distance <<= kNumAlignBits;
+            {
+              unsigned i = 1;
+              GET_BIT2(prob + i, i, ; , distance |= 1);
+              GET_BIT2(prob + i, i, ; , distance |= 2);
+              GET_BIT2(prob + i, i, ; , distance |= 4);
+              GET_BIT2(prob + i, i, ; , distance |= 8);
+            }
+            if (distance == (UInt32)0xFFFFFFFF)
+            {
+              len += kMatchSpecLenStart;
+              state -= kNumStates;
+              break;
+            }
+          }
+        }
+        rep3 = rep2;
+        rep2 = rep1;
+        rep1 = rep0;
+        rep0 = distance + 1;
+        if (checkDicSize == 0)
+        {
+          if (distance >= processedPos)
+            return SZ_ERROR_DATA;
+        }
+        else if (distance >= checkDicSize)
+          return SZ_ERROR_DATA;
+        state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;
+      }
+
+      len += kMatchMinLen;
+
+      if (limit == dicPos)
+        return SZ_ERROR_DATA;
+      {
+        SizeT rem = limit - dicPos;
+        unsigned curLen = ((rem < len) ? (unsigned)rem : len);
+        SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0);
+
+        processedPos += curLen;
+
+        len -= curLen;
+        if (pos + curLen <= dicBufSize)
+        {
+          Byte *dest = dic + dicPos;
+          ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos;
+          const Byte *lim = dest + curLen;
+          dicPos += curLen;
+          do
+            *(dest) = (Byte)*(dest + src);
+          while (++dest != lim);
+        }
+        else
+        {
+          do
+          {
+            dic[dicPos++] = dic[pos];
+            if (++pos == dicBufSize)
+              pos = 0;
+          }
+          while (--curLen != 0);
+        }
+      }
+    }
+  }
+  while (dicPos < limit && buf < bufLimit);
+  NORMALIZE;
+  p->buf = buf;
+  p->range = range;
+  p->code = code;
+  p->remainLen = len;
+  p->dicPos = dicPos;
+  p->processedPos = processedPos;
+  p->reps[0] = rep0;
+  p->reps[1] = rep1;
+  p->reps[2] = rep2;
+  p->reps[3] = rep3;
+  p->state = state;
+
+  return SZ_OK;
+}
+
+static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
+{
+  if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart)
+  {
+    Byte *dic = p->dic;
+    SizeT dicPos = p->dicPos;
+    SizeT dicBufSize = p->dicBufSize;
+    unsigned len = p->remainLen;
+    UInt32 rep0 = p->reps[0];
+    if (limit - dicPos < len)
+      len = (unsigned)(limit - dicPos);
+
+    if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len)
+      p->checkDicSize = p->prop.dicSize;
+
+    p->processedPos += len;
+    p->remainLen -= len;
+    while (len-- != 0)
+    {
+      dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
+      dicPos++;
+    }
+    p->dicPos = dicPos;
+  }
+}
+
+static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
+{
+  do
+  {
+    SizeT limit2 = limit;
+    if (p->checkDicSize == 0)
+    {
+      UInt32 rem = p->prop.dicSize - p->processedPos;
+      if (limit - p->dicPos > rem)
+        limit2 = p->dicPos + rem;
+    }
+    RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit));
+    if (p->processedPos >= p->prop.dicSize)
+      p->checkDicSize = p->prop.dicSize;
+    LzmaDec_WriteRem(p, limit);
+  }
+  while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart);
+
+  if (p->remainLen > kMatchSpecLenStart)
+  {
+    p->remainLen = kMatchSpecLenStart;
+  }
+  return 0;
+}
+
+typedef enum
+{
+  DUMMY_ERROR, /* unexpected end of input stream */
+  DUMMY_LIT,
+  DUMMY_MATCH,
+  DUMMY_REP
+} ELzmaDummy;
+
+static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize)
+{
+  UInt32 range = p->range;
+  UInt32 code = p->code;
+  const Byte *bufLimit = buf + inSize;
+  CLzmaProb *probs = p->probs;
+  unsigned state = p->state;
+  ELzmaDummy res;
+
+  {
+    CLzmaProb *prob;
+    UInt32 bound;
+    unsigned ttt;
+    unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1);
+
+    prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;
+    IF_BIT_0_CHECK(prob)
+    {
+      UPDATE_0_CHECK
+
+      /* if (bufLimit - buf >= 7) return DUMMY_LIT; */
+
+      prob = probs + Literal;
+      if (p->checkDicSize != 0 || p->processedPos != 0)
+        prob += (LZMA_LIT_SIZE *
+          ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) +
+          (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc))));
+
+      if (state < kNumLitStates)
+      {
+        unsigned symbol = 1;
+        do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100);
+      }
+      else
+      {
+        unsigned matchByte = p->dic[p->dicPos - p->reps[0] +
+            ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)];
+        unsigned offs = 0x100;
+        unsigned symbol = 1;
+        do
+        {
+          unsigned bit;
+          CLzmaProb *probLit;
+          matchByte <<= 1;
+          bit = (matchByte & offs);
+          probLit = prob + offs + bit + symbol;
+          GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit)
+        }
+        while (symbol < 0x100);
+      }
+      res = DUMMY_LIT;
+    }
+    else
+    {
+      unsigned len;
+      UPDATE_1_CHECK;
+
+      prob = probs + IsRep + state;
+      IF_BIT_0_CHECK(prob)
+      {
+        UPDATE_0_CHECK;
+        state = 0;
+        prob = probs + LenCoder;
+        res = DUMMY_MATCH;
+      }
+      else
+      {
+        UPDATE_1_CHECK;
+        res = DUMMY_REP;
+        prob = probs + IsRepG0 + state;
+        IF_BIT_0_CHECK(prob)
+        {
+          UPDATE_0_CHECK;
+          prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;
+          IF_BIT_0_CHECK(prob)
+          {
+            UPDATE_0_CHECK;
+            NORMALIZE_CHECK;
+            return DUMMY_REP;
+          }
+          else
+          {
+            UPDATE_1_CHECK;
+          }
+        }
+        else
+        {
+          UPDATE_1_CHECK;
+          prob = probs + IsRepG1 + state;
+          IF_BIT_0_CHECK(prob)
+          {
+            UPDATE_0_CHECK;
+          }
+          else
+          {
+            UPDATE_1_CHECK;
+            prob = probs + IsRepG2 + state;
+            IF_BIT_0_CHECK(prob)
+            {
+              UPDATE_0_CHECK;
+            }
+            else
+            {
+              UPDATE_1_CHECK;
+            }
+          }
+        }
+        state = kNumStates;
+        prob = probs + RepLenCoder;
+      }
+      {
+        unsigned limit, offset;
+        CLzmaProb *probLen = prob + LenChoice;
+        IF_BIT_0_CHECK(probLen)
+        {
+          UPDATE_0_CHECK;
+          probLen = prob + LenLow + (posState << kLenNumLowBits);
+          offset = 0;
+          limit = 1 << kLenNumLowBits;
+        }
+        else
+        {
+          UPDATE_1_CHECK;
+          probLen = prob + LenChoice2;
+          IF_BIT_0_CHECK(probLen)
+          {
+            UPDATE_0_CHECK;
+            probLen = prob + LenMid + (posState << kLenNumMidBits);
+            offset = kLenNumLowSymbols;
+            limit = 1 << kLenNumMidBits;
+          }
+          else
+          {
+            UPDATE_1_CHECK;
+            probLen = prob + LenHigh;
+            offset = kLenNumLowSymbols + kLenNumMidSymbols;
+            limit = 1 << kLenNumHighBits;
+          }
+        }
+        TREE_DECODE_CHECK(probLen, limit, len);
+        len += offset;
+      }
+
+      if (state < 4)
+      {
+        unsigned posSlot;
+        prob = probs + PosSlot +
+            ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
+            kNumPosSlotBits);
+        TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot);
+        if (posSlot >= kStartPosModelIndex)
+        {
+          int numDirectBits = ((posSlot >> 1) - 1);
+
+          /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */
+
+          if (posSlot < kEndPosModelIndex)
+          {
+            prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1;
+          }
+          else
+          {
+            numDirectBits -= kNumAlignBits;
+            do
+            {
+              NORMALIZE_CHECK
+              range >>= 1;
+              code -= range & (((code - range) >> 31) - 1);
+              /* if (code >= range) code -= range; */
+            }
+            while (--numDirectBits != 0);
+            prob = probs + Align;
+            numDirectBits = kNumAlignBits;
+          }
+          {
+            unsigned i = 1;
+            do
+            {
+              GET_BIT_CHECK(prob + i, i);
+            }
+            while (--numDirectBits != 0);
+          }
+        }
+      }
+    }
+  }
+  NORMALIZE_CHECK;
+  return res;
+}
+
+
+static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data)
+{
+  p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]);
+  p->range = 0xFFFFFFFF;
+  p->needFlush = 0;
+}
+
+static void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState)
+{
+  p->needFlush = 1;
+  p->remainLen = 0;
+  p->tempBufSize = 0;
+
+  if (initDic)
+  {
+    p->processedPos = 0;
+    p->checkDicSize = 0;
+    p->needInitState = 1;
+  }
+  if (initState)
+    p->needInitState = 1;
+}
+
+static void LzmaDec_Init(CLzmaDec *p)
+{
+  p->dicPos = 0;
+  LzmaDec_InitDicAndState(p, True, True);
+}
+
+static void LzmaDec_InitStateReal(CLzmaDec *p)
+{
+  UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp));
+  UInt32 i;
+  CLzmaProb *probs = p->probs;
+  for (i = 0; i < numProbs; i++)
+    probs[i] = kBitModelTotal >> 1;
+  p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1;
+  p->state = 0;
+  p->needInitState = 0;
+}
+
+static SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen,
+    ELzmaFinishMode finishMode, ELzmaStatus *status)
+{
+  SizeT inSize = *srcLen;
+  (*srcLen) = 0;
+  LzmaDec_WriteRem(p, dicLimit);
+  
+  *status = LZMA_STATUS_NOT_SPECIFIED;
+
+  while (p->remainLen != kMatchSpecLenStart)
+  {
+      int checkEndMarkNow;
+
+      if (p->needFlush != 0)
+      {
+        for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--)
+          p->tempBuf[p->tempBufSize++] = *src++;
+        if (p->tempBufSize < RC_INIT_SIZE)
+        {
+          *status = LZMA_STATUS_NEEDS_MORE_INPUT;
+          return SZ_OK;
+        }
+        if (p->tempBuf[0] != 0)
+          return SZ_ERROR_DATA;
+
+        LzmaDec_InitRc(p, p->tempBuf);
+        p->tempBufSize = 0;
+      }
+
+      checkEndMarkNow = 0;
+      if (p->dicPos >= dicLimit)
+      {
+        if (p->remainLen == 0 && p->code == 0)
+        {
+          *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK;
+          return SZ_OK;
+        }
+        if (finishMode == LZMA_FINISH_ANY)
+        {
+          *status = LZMA_STATUS_NOT_FINISHED;
+          return SZ_OK;
+        }
+        if (p->remainLen != 0)
+        {
+          *status = LZMA_STATUS_NOT_FINISHED;
+          return SZ_ERROR_DATA;
+        }
+        checkEndMarkNow = 1;
+      }
+
+      if (p->needInitState)
+        LzmaDec_InitStateReal(p);
+  
+      if (p->tempBufSize == 0)
+      {
+        SizeT processed;
+        const Byte *bufLimit;
+        if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
+        {
+          int dummyRes = LzmaDec_TryDummy(p, src, inSize);
+          if (dummyRes == DUMMY_ERROR)
+          {
+            memcpy(p->tempBuf, src, inSize);
+            p->tempBufSize = (unsigned)inSize;
+            (*srcLen) += inSize;
+            *status = LZMA_STATUS_NEEDS_MORE_INPUT;
+            return SZ_OK;
+          }
+          if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
+          {
+            *status = LZMA_STATUS_NOT_FINISHED;
+            return SZ_ERROR_DATA;
+          }
+          bufLimit = src;
+        }
+        else
+          bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX;
+        p->buf = src;
+        if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0)
+          return SZ_ERROR_DATA;
+        processed = (SizeT)(p->buf - src);
+        (*srcLen) += processed;
+        src += processed;
+        inSize -= processed;
+      }
+      else
+      {
+        unsigned rem = p->tempBufSize, lookAhead = 0;
+        while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize)
+          p->tempBuf[rem++] = src[lookAhead++];
+        p->tempBufSize = rem;
+        if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
+        {
+          int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem);
+          if (dummyRes == DUMMY_ERROR)
+          {
+            (*srcLen) += lookAhead;
+            *status = LZMA_STATUS_NEEDS_MORE_INPUT;
+            return SZ_OK;
+          }
+          if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
+          {
+            *status = LZMA_STATUS_NOT_FINISHED;
+            return SZ_ERROR_DATA;
+          }
+        }
+        p->buf = p->tempBuf;
+        if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0)
+          return SZ_ERROR_DATA;
+        lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf));
+        (*srcLen) += lookAhead;
+        src += lookAhead;
+        inSize -= lookAhead;
+        p->tempBufSize = 0;
+      }
+  }
+  if (p->code == 0)
+    *status = LZMA_STATUS_FINISHED_WITH_MARK;
+  return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA;
+}
+
+static __maybe_unused SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
+{
+  SizeT outSize = *destLen;
+  SizeT inSize = *srcLen;
+  *srcLen = *destLen = 0;
+  for (;;)
+  {
+    SizeT inSizeCur = inSize, outSizeCur, dicPos;
+    ELzmaFinishMode curFinishMode;
+    SRes res;
+    if (p->dicPos == p->dicBufSize)
+      p->dicPos = 0;
+    dicPos = p->dicPos;
+    if (outSize > p->dicBufSize - dicPos)
+    {
+      outSizeCur = p->dicBufSize;
+      curFinishMode = LZMA_FINISH_ANY;
+    }
+    else
+    {
+      outSizeCur = dicPos + outSize;
+      curFinishMode = finishMode;
+    }
+
+    res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status);
+    src += inSizeCur;
+    inSize -= inSizeCur;
+    *srcLen += inSizeCur;
+    outSizeCur = p->dicPos - dicPos;
+    memcpy(dest, p->dic + dicPos, outSizeCur);
+    dest += outSizeCur;
+    outSize -= outSizeCur;
+    *destLen += outSizeCur;
+    if (res != 0)
+      return res;
+    if (outSizeCur == 0 || outSize == 0)
+      return SZ_OK;
+  }
+}
+
+static void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc)
+{
+  alloc->Free(alloc, p->probs);
+  p->probs = 0;
+}
+
+static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc)
+{
+  alloc->Free(alloc, p->dic);
+  p->dic = 0;
+}
+
+static void __maybe_unused LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc)
+{
+  LzmaDec_FreeProbs(p, alloc);
+  LzmaDec_FreeDict(p, alloc);
+}
+
+static SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size)
+{
+  UInt32 dicSize;
+  Byte d;
+  
+  if (size < LZMA_PROPS_SIZE)
+    return SZ_ERROR_UNSUPPORTED;
+  else
+    dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24);
+ 
+  if (dicSize < LZMA_DIC_MIN)
+    dicSize = LZMA_DIC_MIN;
+  p->dicSize = dicSize;
+
+  d = data[0];
+  if (d >= (9 * 5 * 5))
+    return SZ_ERROR_UNSUPPORTED;
+
+  p->lc = d % 9;
+  d /= 9;
+  p->pb = d / 5;
+  p->lp = d % 5;
+
+  return SZ_OK;
+}
+
+static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc)
+{
+  UInt32 numProbs = LzmaProps_GetNumProbs(propNew);
+  if (p->probs == 0 || numProbs != p->numProbs)
+  {
+    LzmaDec_FreeProbs(p, alloc);
+    p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb));
+    p->numProbs = numProbs;
+    if (p->probs == 0)
+      return SZ_ERROR_MEM;
+  }
+  return SZ_OK;
+}
+
+static SRes __maybe_unused LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
+{
+  CLzmaProps propNew;
+  RINOK(LzmaProps_Decode(&propNew, props, propsSize));
+  RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
+  p->prop = propNew;
+  return SZ_OK;
+}
+
+static SRes __maybe_unused LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
+{
+  CLzmaProps propNew;
+  SizeT dicBufSize;
+  RINOK(LzmaProps_Decode(&propNew, props, propsSize));
+  RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
+  dicBufSize = propNew.dicSize;
+  if (p->dic == 0 || dicBufSize != p->dicBufSize)
+  {
+    LzmaDec_FreeDict(p, alloc);
+    p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize);
+    if (p->dic == 0)
+    {
+      LzmaDec_FreeProbs(p, alloc);
+      return SZ_ERROR_MEM;
+    }
+  }
+  p->dicBufSize = dicBufSize;
+  p->prop = propNew;
+  return SZ_OK;
+}
+
+SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
+    const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
+    ELzmaStatus *status, ISzAlloc *alloc)
+{
+  CLzmaDec p;
+  SRes res;
+  SizeT inSize = *srcLen;
+  SizeT outSize = *destLen;
+  *srcLen = *destLen = 0;
+  if (inSize < RC_INIT_SIZE)
+    return SZ_ERROR_INPUT_EOF;
+
+  LzmaDec_Construct(&p);
+  res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc);
+  if (res != 0)
+    return res;
+  p.dic = dest;
+  p.dicBufSize = outSize;
+
+  LzmaDec_Init(&p);
+  
+  *srcLen = inSize;
+  res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
+
+  if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
+    res = SZ_ERROR_INPUT_EOF;
+
+  (*destLen) = p.dicPos;
+  LzmaDec_FreeProbs(&p, alloc);
+  return res;
+}
diff --git a/lib/lzma/LzmaEnc.c b/lib/lzma/LzmaEnc.c
new file mode 100644
index 0000000..17afd01
--- /dev/null
+++ b/lib/lzma/LzmaEnc.c
@@ -0,0 +1,2271 @@
+/* LzmaEnc.c -- LZMA Encoder
+2009-11-24 : Igor Pavlov : Public domain */
+
+#include <string.h>
+
+/* #define SHOW_STAT */
+/* #define SHOW_STAT2 */
+
+#if defined(SHOW_STAT) || defined(SHOW_STAT2)
+#include <stdio.h>
+#endif
+
+#include "LzmaEnc.h"
+
+/* disable MT */
+#define _7ZIP_ST
+
+#include "LzFind.h"
+#ifndef _7ZIP_ST
+#include "LzFindMt.h"
+#endif
+
+#ifdef SHOW_STAT
+static int ttt = 0;
+#endif
+
+#define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1)
+
+#define kBlockSize (9 << 10)
+#define kUnpackBlockSize (1 << 18)
+#define kMatchArraySize (1 << 21)
+#define kMatchRecordMaxSize ((LZMA_MATCH_LEN_MAX * 2 + 3) * LZMA_MATCH_LEN_MAX)
+
+#define kNumMaxDirectBits (31)
+
+#define kNumTopBits 24
+#define kTopValue ((UInt32)1 << kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
+#define kNumMoveBits 5
+#define kProbInitValue (kBitModelTotal >> 1)
+
+#define kNumMoveReducingBits 4
+#define kNumBitPriceShiftBits 4
+#define kBitPrice (1 << kNumBitPriceShiftBits)
+
+void LzmaEncProps_Init(CLzmaEncProps *p)
+{
+  p->level = 5;
+  p->dictSize = p->mc = 0;
+  p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1;
+  p->writeEndMark = 0;
+}
+
+static void LzmaEncProps_Normalize(CLzmaEncProps *p)
+{
+  int level = p->level;
+  if (level < 0) level = 5;
+  p->level = level;
+  if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26)));
+  if (p->lc < 0) p->lc = 3;
+  if (p->lp < 0) p->lp = 0;
+  if (p->pb < 0) p->pb = 2;
+  if (p->algo < 0) p->algo = (level < 5 ? 0 : 1);
+  if (p->fb < 0) p->fb = (level < 7 ? 32 : 64);
+  if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1);
+  if (p->numHashBytes < 0) p->numHashBytes = 4;
+  if (p->mc == 0)  p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1);
+  if (p->numThreads < 0)
+    p->numThreads =
+      #ifndef _7ZIP_ST
+      ((p->btMode && p->algo) ? 2 : 1);
+      #else
+      1;
+      #endif
+}
+
+static UInt32 __maybe_unused LzmaEncProps_GetDictSize(const CLzmaEncProps *props2)
+{
+  CLzmaEncProps props = *props2;
+  LzmaEncProps_Normalize(&props);
+  return props.dictSize;
+}
+
+/* #define LZMA_LOG_BSR */
+/* Define it for Intel's CPU */
+
+
+#ifdef LZMA_LOG_BSR
+
+#define kDicLogSizeMaxCompress 30
+
+#define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); }
+
+static UInt32 GetPosSlot1(UInt32 pos)
+{
+  UInt32 res;
+  BSR2_RET(pos, res);
+  return res;
+}
+#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }
+#define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); }
+
+#else
+
+#define kNumLogBits (9 + (int)sizeof(size_t) / 2)
+#define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7)
+
+static void LzmaEnc_FastPosInit(Byte *g_FastPos)
+{
+  int c = 2, slotFast;
+  g_FastPos[0] = 0;
+  g_FastPos[1] = 1;
+  
+  for (slotFast = 2; slotFast < kNumLogBits * 2; slotFast++)
+  {
+    UInt32 k = (1 << ((slotFast >> 1) - 1));
+    UInt32 j;
+    for (j = 0; j < k; j++, c++)
+      g_FastPos[c] = (Byte)slotFast;
+  }
+}
+
+#define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) & \
+  (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \
+  res = p->g_FastPos[pos >> i] + (i * 2); }
+/*
+#define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \
+  p->g_FastPos[pos >> 6] + 12 : \
+  p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; }
+*/
+
+#define GetPosSlot1(pos) p->g_FastPos[pos]
+#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }
+#define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos]; else BSR2_RET(pos, res); }
+
+#endif
+
+
+#define LZMA_NUM_REPS 4
+
+typedef unsigned CState;
+
+typedef struct
+{
+  UInt32 price;
+
+  CState state;
+  int prev1IsChar;
+  int prev2;
+
+  UInt32 posPrev2;
+  UInt32 backPrev2;
+
+  UInt32 posPrev;
+  UInt32 backPrev;
+  UInt32 backs[LZMA_NUM_REPS];
+} COptimal;
+
+#define kNumOpts (1 << 12)
+
+#define kNumLenToPosStates 4
+#define kNumPosSlotBits 6
+#define kDicLogSizeMin 0
+#define kDicLogSizeMax 32
+#define kDistTableSizeMax (kDicLogSizeMax * 2)
+
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 << kNumAlignBits)
+#define kAlignMask (kAlignTableSize - 1)
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumPosModels (kEndPosModelIndex - kStartPosModelIndex)
+
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+
+#ifdef _LZMA_PROB32
+#define CLzmaProb UInt32
+#else
+#define CLzmaProb UInt16
+#endif
+
+#define LZMA_PB_MAX 4
+#define LZMA_LC_MAX 8
+#define LZMA_LP_MAX 4
+
+#define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX)
+
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
+#define kLenNumMidBits 3
+#define kLenNumMidSymbols (1 << kLenNumMidBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
+
+#define kLenNumSymbolsTotal (kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)
+
+#define LZMA_MATCH_LEN_MIN 2
+#define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1)
+
+#define kNumStates 12
+
+typedef struct
+{
+  CLzmaProb choice;
+  CLzmaProb choice2;
+  CLzmaProb low[LZMA_NUM_PB_STATES_MAX << kLenNumLowBits];
+  CLzmaProb mid[LZMA_NUM_PB_STATES_MAX << kLenNumMidBits];
+  CLzmaProb high[kLenNumHighSymbols];
+} CLenEnc;
+
+typedef struct
+{
+  CLenEnc p;
+  UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal];
+  UInt32 tableSize;
+  UInt32 counters[LZMA_NUM_PB_STATES_MAX];
+} CLenPriceEnc;
+
+typedef struct
+{
+  UInt32 range;
+  Byte cache;
+  UInt64 low;
+  UInt64 cacheSize;
+  Byte *buf;
+  Byte *bufLim;
+  Byte *bufBase;
+  ISeqOutStream *outStream;
+  UInt64 processed;
+  SRes res;
+} CRangeEnc;
+
+typedef struct
+{
+  CLzmaProb *litProbs;
+
+  CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
+  CLzmaProb isRep[kNumStates];
+  CLzmaProb isRepG0[kNumStates];
+  CLzmaProb isRepG1[kNumStates];
+  CLzmaProb isRepG2[kNumStates];
+  CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];
+
+  CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];
+  CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex];
+  CLzmaProb posAlignEncoder[1 << kNumAlignBits];
+  
+  CLenPriceEnc lenEnc;
+  CLenPriceEnc repLenEnc;
+
+  UInt32 reps[LZMA_NUM_REPS];
+  UInt32 state;
+} CSaveState;
+
+typedef struct
+{
+  IMatchFinder matchFinder;
+  void *matchFinderObj;
+
+  #ifndef _7ZIP_ST
+  Bool mtMode;
+  CMatchFinderMt matchFinderMt;
+  #endif
+
+  CMatchFinder matchFinderBase;
+
+  #ifndef _7ZIP_ST
+  Byte pad[128];
+  #endif
+  
+  UInt32 optimumEndIndex;
+  UInt32 optimumCurrentIndex;
+
+  UInt32 longestMatchLength;
+  UInt32 numPairs;
+  UInt32 numAvail;
+  COptimal opt[kNumOpts];
+  
+  #ifndef LZMA_LOG_BSR
+  Byte g_FastPos[1 << kNumLogBits];
+  #endif
+
+  UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits];
+  UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1];
+  UInt32 numFastBytes;
+  UInt32 additionalOffset;
+  UInt32 reps[LZMA_NUM_REPS];
+  UInt32 state;
+
+  UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax];
+  UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances];
+  UInt32 alignPrices[kAlignTableSize];
+  UInt32 alignPriceCount;
+
+  UInt32 distTableSize;
+
+  unsigned lc, lp, pb;
+  unsigned lpMask, pbMask;
+
+  CLzmaProb *litProbs;
+
+  CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
+  CLzmaProb isRep[kNumStates];
+  CLzmaProb isRepG0[kNumStates];
+  CLzmaProb isRepG1[kNumStates];
+  CLzmaProb isRepG2[kNumStates];
+  CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];
+
+  CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];
+  CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex];
+  CLzmaProb posAlignEncoder[1 << kNumAlignBits];
+  
+  CLenPriceEnc lenEnc;
+  CLenPriceEnc repLenEnc;
+
+  unsigned lclp;
+
+  Bool fastMode;
+  
+  CRangeEnc rc;
+
+  Bool writeEndMark;
+  UInt64 nowPos64;
+  UInt32 matchPriceCount;
+  Bool finished;
+  Bool multiThread;
+
+  SRes result;
+  UInt32 dictSize;
+  UInt32 matchFinderCycles;
+
+  int needInit;
+
+  CSaveState saveState;
+} CLzmaEnc;
+
+static void __maybe_unused LzmaEnc_SaveState(CLzmaEncHandle pp)
+{
+  CLzmaEnc *p = (CLzmaEnc *)pp;
+  CSaveState *dest = &p->saveState;
+  int i;
+  dest->lenEnc = p->lenEnc;
+  dest->repLenEnc = p->repLenEnc;
+  dest->state = p->state;
+
+  for (i = 0; i < kNumStates; i++)
+  {
+    memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i]));
+    memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i]));
+  }
+  for (i = 0; i < kNumLenToPosStates; i++)
+    memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i]));
+  memcpy(dest->isRep, p->isRep, sizeof(p->isRep));
+  memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0));
+  memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1));
+  memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2));
+  memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders));
+  memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder));
+  memcpy(dest->reps, p->reps, sizeof(p->reps));
+  memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb));
+}
+
+static void __maybe_unused LzmaEnc_RestoreState(CLzmaEncHandle pp)
+{
+  CLzmaEnc *dest = (CLzmaEnc *)pp;
+  const CSaveState *p = &dest->saveState;
+  int i;
+  dest->lenEnc = p->lenEnc;
+  dest->repLenEnc = p->repLenEnc;
+  dest->state = p->state;
+
+  for (i = 0; i < kNumStates; i++)
+  {
+    memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i]));
+    memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i]));
+  }
+  for (i = 0; i < kNumLenToPosStates; i++)
+    memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i]));
+  memcpy(dest->isRep, p->isRep, sizeof(p->isRep));
+  memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0));
+  memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1));
+  memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2));
+  memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders));
+  memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder));
+  memcpy(dest->reps, p->reps, sizeof(p->reps));
+  memcpy(dest->litProbs, p->litProbs, (0x300 << dest->lclp) * sizeof(CLzmaProb));
+}
+
+SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)
+{
+  CLzmaEnc *p = (CLzmaEnc *)pp;
+  CLzmaEncProps props = *props2;
+  LzmaEncProps_Normalize(&props);
+
+  if (props.lc > LZMA_LC_MAX || props.lp > LZMA_LP_MAX || props.pb > LZMA_PB_MAX ||
+      props.dictSize > (1 << kDicLogSizeMaxCompress) || props.dictSize > (1 << 30))
+    return SZ_ERROR_PARAM;
+  p->dictSize = props.dictSize;
+  p->matchFinderCycles = props.mc;
+  {
+    unsigned fb = props.fb;
+    if (fb < 5)
+      fb = 5;
+    if (fb > LZMA_MATCH_LEN_MAX)
+      fb = LZMA_MATCH_LEN_MAX;
+    p->numFastBytes = fb;
+  }
+  p->lc = props.lc;
+  p->lp = props.lp;
+  p->pb = props.pb;
+  p->fastMode = (props.algo == 0);
+  p->matchFinderBase.btMode = props.btMode;
+  {
+    UInt32 numHashBytes = 4;
+    if (props.btMode)
+    {
+      if (props.numHashBytes < 2)
+        numHashBytes = 2;
+      else if (props.numHashBytes < 4)
+        numHashBytes = props.numHashBytes;
+    }
+    p->matchFinderBase.numHashBytes = numHashBytes;
+  }
+
+  p->matchFinderBase.cutValue = props.mc;
+
+  p->writeEndMark = props.writeEndMark;
+
+  #ifndef _7ZIP_ST
+  /*
+  if (newMultiThread != _multiThread)
+  {
+    ReleaseMatchFinder();
+    _multiThread = newMultiThread;
+  }
+  */
+  p->multiThread = (props.numThreads > 1);
+  #endif
+
+  return SZ_OK;
+}
+
+static const int kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4,  5,  6,   4, 5};
+static const int kMatchNextStates[kNumStates]   = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};
+static const int kRepNextStates[kNumStates]     = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};
+static const int kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};
+
+#define IsCharState(s) ((s) < 7)
+
+#define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1)
+
+#define kInfinityPrice (1 << 30)
+
+static void RangeEnc_Construct(CRangeEnc *p)
+{
+  p->outStream = 0;
+  p->bufBase = 0;
+}
+
+#define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize)
+
+#define RC_BUF_SIZE (1 << 16)
+static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc)
+{
+  if (p->bufBase == 0)
+  {
+    p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE);
+    if (p->bufBase == 0)
+      return 0;
+    p->bufLim = p->bufBase + RC_BUF_SIZE;
+  }
+  return 1;
+}
+
+static void RangeEnc_Free(CRangeEnc *p, ISzAlloc *alloc)
+{
+  alloc->Free(alloc, p->bufBase);
+  p->bufBase = 0;
+}
+
+static void RangeEnc_Init(CRangeEnc *p)
+{
+  /* Stream.Init(); */
+  p->low = 0;
+  p->range = 0xFFFFFFFF;
+  p->cacheSize = 1;
+  p->cache = 0;
+
+  p->buf = p->bufBase;
+
+  p->processed = 0;
+  p->res = SZ_OK;
+}
+
+static void RangeEnc_FlushStream(CRangeEnc *p)
+{
+  size_t num;
+  if (p->res != SZ_OK)
+    return;
+  num = p->buf - p->bufBase;
+  if (num != p->outStream->Write(p->outStream, p->bufBase, num))
+    p->res = SZ_ERROR_WRITE;
+  p->processed += num;
+  p->buf = p->bufBase;
+}
+
+static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p)
+{
+  if ((UInt32)p->low < (UInt32)0xFF000000 || (int)(p->low >> 32) != 0)
+  {
+    Byte temp = p->cache;
+    do
+    {
+      Byte *buf = p->buf;
+      *buf++ = (Byte)(temp + (Byte)(p->low >> 32));
+      p->buf = buf;
+      if (buf == p->bufLim)
+        RangeEnc_FlushStream(p);
+      temp = 0xFF;
+    }
+    while (--p->cacheSize != 0);
+    p->cache = (Byte)((UInt32)p->low >> 24);
+  }
+  p->cacheSize++;
+  p->low = (UInt32)p->low << 8;
+}
+
+static void RangeEnc_FlushData(CRangeEnc *p)
+{
+  int i;
+  for (i = 0; i < 5; i++)
+    RangeEnc_ShiftLow(p);
+}
+
+static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, int numBits)
+{
+  do
+  {
+    p->range >>= 1;
+    p->low += p->range & (0 - ((value >> --numBits) & 1));
+    if (p->range < kTopValue)
+    {
+      p->range <<= 8;
+      RangeEnc_ShiftLow(p);
+    }
+  }
+  while (numBits != 0);
+}
+
+static void RangeEnc_EncodeBit(CRangeEnc *p, CLzmaProb *prob, UInt32 symbol)
+{
+  UInt32 ttt = *prob;
+  UInt32 newBound = (p->range >> kNumBitModelTotalBits) * ttt;
+  if (symbol == 0)
+  {
+    p->range = newBound;
+    ttt += (kBitModelTotal - ttt) >> kNumMoveBits;
+  }
+  else
+  {
+    p->low += newBound;
+    p->range -= newBound;
+    ttt -= ttt >> kNumMoveBits;
+  }
+  *prob = (CLzmaProb)ttt;
+  if (p->range < kTopValue)
+  {
+    p->range <<= 8;
+    RangeEnc_ShiftLow(p);
+  }
+}
+
+static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol)
+{
+  symbol |= 0x100;
+  do
+  {
+    RangeEnc_EncodeBit(p, probs + (symbol >> 8), (symbol >> 7) & 1);
+    symbol <<= 1;
+  }
+  while (symbol < 0x10000);
+}
+
+static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol, UInt32 matchByte)
+{
+  UInt32 offs = 0x100;
+  symbol |= 0x100;
+  do
+  {
+    matchByte <<= 1;
+    RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (symbol >> 8)), (symbol >> 7) & 1);
+    symbol <<= 1;
+    offs &= ~(matchByte ^ symbol);
+  }
+  while (symbol < 0x10000);
+}
+
+static void LzmaEnc_InitPriceTables(UInt32 *ProbPrices)
+{
+  UInt32 i;
+  for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits))
+  {
+    const int kCyclesBits = kNumBitPriceShiftBits;
+    UInt32 w = i;
+    UInt32 bitCount = 0;
+    int j;
+    for (j = 0; j < kCyclesBits; j++)
+    {
+      w = w * w;
+      bitCount <<= 1;
+      while (w >= ((UInt32)1 << 16))
+      {
+        w >>= 1;
+        bitCount++;
+      }
+    }
+    ProbPrices[i >> kNumMoveReducingBits] = ((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount);
+  }
+}
+
+
+#define GET_PRICE(prob, symbol) \
+  p->ProbPrices[((prob) ^ (((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
+
+#define GET_PRICEa(prob, symbol) \
+  ProbPrices[((prob) ^ ((-((int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
+
+#define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits]
+#define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
+
+#define GET_PRICE_0a(prob) ProbPrices[(prob) >> kNumMoveReducingBits]
+#define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
+
+static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 *ProbPrices)
+{
+  UInt32 price = 0;
+  symbol |= 0x100;
+  do
+  {
+    price += GET_PRICEa(probs[symbol >> 8], (symbol >> 7) & 1);
+    symbol <<= 1;
+  }
+  while (symbol < 0x10000);
+  return price;
+}
+
+static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, UInt32 *ProbPrices)
+{
+  UInt32 price = 0;
+  UInt32 offs = 0x100;
+  symbol |= 0x100;
+  do
+  {
+    matchByte <<= 1;
+    price += GET_PRICEa(probs[offs + (matchByte & offs) + (symbol >> 8)], (symbol >> 7) & 1);
+    symbol <<= 1;
+    offs &= ~(matchByte ^ symbol);
+  }
+  while (symbol < 0x10000);
+  return price;
+}
+
+
+static void RcTree_Encode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol)
+{
+  UInt32 m = 1;
+  int i;
+  for (i = numBitLevels; i != 0;)
+  {
+    UInt32 bit;
+    i--;
+    bit = (symbol >> i) & 1;
+    RangeEnc_EncodeBit(rc, probs + m, bit);
+    m = (m << 1) | bit;
+  }
+}
+
+static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol)
+{
+  UInt32 m = 1;
+  int i;
+  for (i = 0; i < numBitLevels; i++)
+  {
+    UInt32 bit = symbol & 1;
+    RangeEnc_EncodeBit(rc, probs + m, bit);
+    m = (m << 1) | bit;
+    symbol >>= 1;
+  }
+}
+
+static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices)
+{
+  UInt32 price = 0;
+  symbol |= (1 << numBitLevels);
+  while (symbol != 1)
+  {
+    price += GET_PRICEa(probs[symbol >> 1], symbol & 1);
+    symbol >>= 1;
+  }
+  return price;
+}
+
+static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices)
+{
+  UInt32 price = 0;
+  UInt32 m = 1;
+  int i;
+  for (i = numBitLevels; i != 0; i--)
+  {
+    UInt32 bit = symbol & 1;
+    symbol >>= 1;
+    price += GET_PRICEa(probs[m], bit);
+    m = (m << 1) | bit;
+  }
+  return price;
+}
+
+
+static void LenEnc_Init(CLenEnc *p)
+{
+  unsigned i;
+  p->choice = p->choice2 = kProbInitValue;
+  for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumLowBits); i++)
+    p->low[i] = kProbInitValue;
+  for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumMidBits); i++)
+    p->mid[i] = kProbInitValue;
+  for (i = 0; i < kLenNumHighSymbols; i++)
+    p->high[i] = kProbInitValue;
+}
+
+static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState)
+{
+  if (symbol < kLenNumLowSymbols)
+  {
+    RangeEnc_EncodeBit(rc, &p->choice, 0);
+    RcTree_Encode(rc, p->low + (posState << kLenNumLowBits), kLenNumLowBits, symbol);
+  }
+  else
+  {
+    RangeEnc_EncodeBit(rc, &p->choice, 1);
+    if (symbol < kLenNumLowSymbols + kLenNumMidSymbols)
+    {
+      RangeEnc_EncodeBit(rc, &p->choice2, 0);
+      RcTree_Encode(rc, p->mid + (posState << kLenNumMidBits), kLenNumMidBits, symbol - kLenNumLowSymbols);
+    }
+    else
+    {
+      RangeEnc_EncodeBit(rc, &p->choice2, 1);
+      RcTree_Encode(rc, p->high, kLenNumHighBits, symbol - kLenNumLowSymbols - kLenNumMidSymbols);
+    }
+  }
+}
+
+static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, UInt32 *ProbPrices)
+{
+  UInt32 a0 = GET_PRICE_0a(p->choice);
+  UInt32 a1 = GET_PRICE_1a(p->choice);
+  UInt32 b0 = a1 + GET_PRICE_0a(p->choice2);
+  UInt32 b1 = a1 + GET_PRICE_1a(p->choice2);
+  UInt32 i = 0;
+  for (i = 0; i < kLenNumLowSymbols; i++)
+  {
+    if (i >= numSymbols)
+      return;
+    prices[i] = a0 + RcTree_GetPrice(p->low + (posState << kLenNumLowBits), kLenNumLowBits, i, ProbPrices);
+  }
+  for (; i < kLenNumLowSymbols + kLenNumMidSymbols; i++)
+  {
+    if (i >= numSymbols)
+      return;
+    prices[i] = b0 + RcTree_GetPrice(p->mid + (posState << kLenNumMidBits), kLenNumMidBits, i - kLenNumLowSymbols, ProbPrices);
+  }
+  for (; i < numSymbols; i++)
+    prices[i] = b1 + RcTree_GetPrice(p->high, kLenNumHighBits, i - kLenNumLowSymbols - kLenNumMidSymbols, ProbPrices);
+}
+
+static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, UInt32 *ProbPrices)
+{
+  LenEnc_SetPrices(&p->p, posState, p->tableSize, p->prices[posState], ProbPrices);
+  p->counters[posState] = p->tableSize;
+}
+
+static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, UInt32 *ProbPrices)
+{
+  UInt32 posState;
+  for (posState = 0; posState < numPosStates; posState++)
+    LenPriceEnc_UpdateTable(p, posState, ProbPrices);
+}
+
+static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, UInt32 *ProbPrices)
+{
+  LenEnc_Encode(&p->p, rc, symbol, posState);
+  if (updatePrice)
+    if (--p->counters[posState] == 0)
+      LenPriceEnc_UpdateTable(p, posState, ProbPrices);
+}
+
+
+
+
+static void MovePos(CLzmaEnc *p, UInt32 num)
+{
+  #ifdef SHOW_STAT
+  ttt += num;
+  printf("\n MovePos %d", num);
+  #endif
+  if (num != 0)
+  {
+    p->additionalOffset += num;
+    p->matchFinder.Skip(p->matchFinderObj, num);
+  }
+}
+
+static UInt32 ReadMatchDistances(CLzmaEnc *p, UInt32 *numDistancePairsRes)
+{
+  UInt32 lenRes = 0, numPairs;
+  p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
+  numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches);
+  #ifdef SHOW_STAT
+  printf("\n i = %d numPairs = %d    ", ttt, numPairs / 2);
+  ttt++;
+  {
+    UInt32 i;
+    for (i = 0; i < numPairs; i += 2)
+      printf("%2d %6d   | ", p->matches[i], p->matches[i + 1]);
+  }
+  #endif
+  if (numPairs > 0)
+  {
+    lenRes = p->matches[numPairs - 2];
+    if (lenRes == p->numFastBytes)
+    {
+      const Byte *pby = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
+      UInt32 distance = p->matches[numPairs - 1] + 1;
+      UInt32 numAvail = p->numAvail;
+      if (numAvail > LZMA_MATCH_LEN_MAX)
+        numAvail = LZMA_MATCH_LEN_MAX;
+      {
+        const Byte *pby2 = pby - distance;
+        for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++);
+      }
+    }
+  }
+  p->additionalOffset++;
+  *numDistancePairsRes = numPairs;
+  return lenRes;
+}
+
+
+#define MakeAsChar(p) (p)->backPrev = (UInt32)(-1); (p)->prev1IsChar = False;
+#define MakeAsShortRep(p) (p)->backPrev = 0; (p)->prev1IsChar = False;
+#define IsShortRep(p) ((p)->backPrev == 0)
+
+static UInt32 GetRepLen1Price(CLzmaEnc *p, UInt32 state, UInt32 posState)
+{
+  return
+    GET_PRICE_0(p->isRepG0[state]) +
+    GET_PRICE_0(p->isRep0Long[state][posState]);
+}
+
+static UInt32 GetPureRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 state, UInt32 posState)
+{
+  UInt32 price;
+  if (repIndex == 0)
+  {
+    price = GET_PRICE_0(p->isRepG0[state]);
+    price += GET_PRICE_1(p->isRep0Long[state][posState]);
+  }
+  else
+  {
+    price = GET_PRICE_1(p->isRepG0[state]);
+    if (repIndex == 1)
+      price += GET_PRICE_0(p->isRepG1[state]);
+    else
+    {
+      price += GET_PRICE_1(p->isRepG1[state]);
+      price += GET_PRICE(p->isRepG2[state], repIndex - 2);
+    }
+  }
+  return price;
+}
+
+static UInt32 GetRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 len, UInt32 state, UInt32 posState)
+{
+  return p->repLenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN] +
+    GetPureRepPrice(p, repIndex, state, posState);
+}
+
+static UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur)
+{
+  UInt32 posMem = p->opt[cur].posPrev;
+  UInt32 backMem = p->opt[cur].backPrev;
+  p->optimumEndIndex = cur;
+  do
+  {
+    if (p->opt[cur].prev1IsChar)
+    {
+      MakeAsChar(&p->opt[posMem])
+      p->opt[posMem].posPrev = posMem - 1;
+      if (p->opt[cur].prev2)
+      {
+        p->opt[posMem - 1].prev1IsChar = False;
+        p->opt[posMem - 1].posPrev = p->opt[cur].posPrev2;
+        p->opt[posMem - 1].backPrev = p->opt[cur].backPrev2;
+      }
+    }
+    {
+      UInt32 posPrev = posMem;
+      UInt32 backCur = backMem;
+      
+      backMem = p->opt[posPrev].backPrev;
+      posMem = p->opt[posPrev].posPrev;
+      
+      p->opt[posPrev].backPrev = backCur;
+      p->opt[posPrev].posPrev = cur;
+      cur = posPrev;
+    }
+  }
+  while (cur != 0);
+  *backRes = p->opt[0].backPrev;
+  p->optimumCurrentIndex  = p->opt[0].posPrev;
+  return p->optimumCurrentIndex;
+}
+
+#define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * 0x300)
+
+static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
+{
+  UInt32 numAvail, mainLen, numPairs, repMaxIndex, i, posState, lenEnd, len, cur;
+  UInt32 matchPrice, repMatchPrice, normalMatchPrice;
+  UInt32 reps[LZMA_NUM_REPS], repLens[LZMA_NUM_REPS];
+  UInt32 *matches;
+  const Byte *data;
+  Byte curByte, matchByte;
+  if (p->optimumEndIndex != p->optimumCurrentIndex)
+  {
+    const COptimal *opt = &p->opt[p->optimumCurrentIndex];
+    UInt32 lenRes = opt->posPrev - p->optimumCurrentIndex;
+    *backRes = opt->backPrev;
+    p->optimumCurrentIndex = opt->posPrev;
+    return lenRes;
+  }
+  p->optimumCurrentIndex = p->optimumEndIndex = 0;
+  
+  if (p->additionalOffset == 0)
+    mainLen = ReadMatchDistances(p, &numPairs);
+  else
+  {
+    mainLen = p->longestMatchLength;
+    numPairs = p->numPairs;
+  }
+
+  numAvail = p->numAvail;
+  if (numAvail < 2)
+  {
+    *backRes = (UInt32)(-1);
+    return 1;
+  }
+  if (numAvail > LZMA_MATCH_LEN_MAX)
+    numAvail = LZMA_MATCH_LEN_MAX;
+
+  data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
+  repMaxIndex = 0;
+  for (i = 0; i < LZMA_NUM_REPS; i++)
+  {
+    UInt32 lenTest;
+    const Byte *data2;
+    reps[i] = p->reps[i];
+    data2 = data - (reps[i] + 1);
+    if (data[0] != data2[0] || data[1] != data2[1])
+    {
+      repLens[i] = 0;
+      continue;
+    }
+    for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++);
+    repLens[i] = lenTest;
+    if (lenTest > repLens[repMaxIndex])
+      repMaxIndex = i;
+  }
+  if (repLens[repMaxIndex] >= p->numFastBytes)
+  {
+    UInt32 lenRes;
+    *backRes = repMaxIndex;
+    lenRes = repLens[repMaxIndex];
+    MovePos(p, lenRes - 1);
+    return lenRes;
+  }
+
+  matches = p->matches;
+  if (mainLen >= p->numFastBytes)
+  {
+    *backRes = matches[numPairs - 1] + LZMA_NUM_REPS;
+    MovePos(p, mainLen - 1);
+    return mainLen;
+  }
+  curByte = *data;
+  matchByte = *(data - (reps[0] + 1));
+
+  if (mainLen < 2 && curByte != matchByte && repLens[repMaxIndex] < 2)
+  {
+    *backRes = (UInt32)-1;
+    return 1;
+  }
+
+  p->opt[0].state = (CState)p->state;
+
+  posState = (position & p->pbMask);
+
+  {
+    const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
+    p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) +
+        (!IsCharState(p->state) ?
+          LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) :
+          LitEnc_GetPrice(probs, curByte, p->ProbPrices));
+  }
+
+  MakeAsChar(&p->opt[1]);
+
+  matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]);
+  repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]);
+
+  if (matchByte == curByte)
+  {
+    UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, p->state, posState);
+    if (shortRepPrice < p->opt[1].price)
+    {
+      p->opt[1].price = shortRepPrice;
+      MakeAsShortRep(&p->opt[1]);
+    }
+  }
+  lenEnd = ((mainLen >= repLens[repMaxIndex]) ? mainLen : repLens[repMaxIndex]);
+
+  if (lenEnd < 2)
+  {
+    *backRes = p->opt[1].backPrev;
+    return 1;
+  }
+
+  p->opt[1].posPrev = 0;
+  for (i = 0; i < LZMA_NUM_REPS; i++)
+    p->opt[0].backs[i] = reps[i];
+
+  len = lenEnd;
+  do
+    p->opt[len--].price = kInfinityPrice;
+  while (len >= 2);
+
+  for (i = 0; i < LZMA_NUM_REPS; i++)
+  {
+    UInt32 repLen = repLens[i];
+    UInt32 price;
+    if (repLen < 2)
+      continue;
+    price = repMatchPrice + GetPureRepPrice(p, i, p->state, posState);
+    do
+    {
+      UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][repLen - 2];
+      COptimal *opt = &p->opt[repLen];
+      if (curAndLenPrice < opt->price)
+      {
+        opt->price = curAndLenPrice;
+        opt->posPrev = 0;
+        opt->backPrev = i;
+        opt->prev1IsChar = False;
+      }
+    }
+    while (--repLen >= 2);
+  }
+
+  normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]);
+
+  len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2);
+  if (len <= mainLen)
+  {
+    UInt32 offs = 0;
+    while (len > matches[offs])
+      offs += 2;
+    for (; ; len++)
+    {
+      COptimal *opt;
+      UInt32 distance = matches[offs + 1];
+
+      UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN];
+      UInt32 lenToPosState = GetLenToPosState(len);
+      if (distance < kNumFullDistances)
+        curAndLenPrice += p->distancesPrices[lenToPosState][distance];
+      else
+      {
+        UInt32 slot;
+        GetPosSlot2(distance, slot);
+        curAndLenPrice += p->alignPrices[distance & kAlignMask] + p->posSlotPrices[lenToPosState][slot];
+      }
+      opt = &p->opt[len];
+      if (curAndLenPrice < opt->price)
+      {
+        opt->price = curAndLenPrice;
+        opt->posPrev = 0;
+        opt->backPrev = distance + LZMA_NUM_REPS;
+        opt->prev1IsChar = False;
+      }
+      if (len == matches[offs])
+      {
+        offs += 2;
+        if (offs == numPairs)
+          break;
+      }
+    }
+  }
+
+  cur = 0;
+
+    #ifdef SHOW_STAT2
+    if (position >= 0)
+    {
+      unsigned i;
+      printf("\n pos = %4X", position);
+      for (i = cur; i <= lenEnd; i++)
+      printf("\nprice[%4X] = %d", position - cur + i, p->opt[i].price);
+    }
+    #endif
+
+  for (;;)
+  {
+    UInt32 numAvailFull, newLen, numPairs, posPrev, state, posState, startLen;
+    UInt32 curPrice, curAnd1Price, matchPrice, repMatchPrice;
+    Bool nextIsChar;
+    Byte curByte, matchByte;
+    const Byte *data;
+    COptimal *curOpt;
+    COptimal *nextOpt;
+
+    cur++;
+    if (cur == lenEnd)
+      return Backward(p, backRes, cur);
+
+    newLen = ReadMatchDistances(p, &numPairs);
+    if (newLen >= p->numFastBytes)
+    {
+      p->numPairs = numPairs;
+      p->longestMatchLength = newLen;
+      return Backward(p, backRes, cur);
+    }
+    position++;
+    curOpt = &p->opt[cur];
+    posPrev = curOpt->posPrev;
+    if (curOpt->prev1IsChar)
+    {
+      posPrev--;
+      if (curOpt->prev2)
+      {
+        state = p->opt[curOpt->posPrev2].state;
+        if (curOpt->backPrev2 < LZMA_NUM_REPS)
+          state = kRepNextStates[state];
+        else
+          state = kMatchNextStates[state];
+      }
+      else
+        state = p->opt[posPrev].state;
+      state = kLiteralNextStates[state];
+    }
+    else
+      state = p->opt[posPrev].state;
+    if (posPrev == cur - 1)
+    {
+      if (IsShortRep(curOpt))
+        state = kShortRepNextStates[state];
+      else
+        state = kLiteralNextStates[state];
+    }
+    else
+    {
+      UInt32 pos;
+      const COptimal *prevOpt;
+      if (curOpt->prev1IsChar && curOpt->prev2)
+      {
+        posPrev = curOpt->posPrev2;
+        pos = curOpt->backPrev2;
+        state = kRepNextStates[state];
+      }
+      else
+      {
+        pos = curOpt->backPrev;
+        if (pos < LZMA_NUM_REPS)
+          state = kRepNextStates[state];
+        else
+          state = kMatchNextStates[state];
+      }
+      prevOpt = &p->opt[posPrev];
+      if (pos < LZMA_NUM_REPS)
+      {
+        UInt32 i;
+        reps[0] = prevOpt->backs[pos];
+        for (i = 1; i <= pos; i++)
+          reps[i] = prevOpt->backs[i - 1];
+        for (; i < LZMA_NUM_REPS; i++)
+          reps[i] = prevOpt->backs[i];
+      }
+      else
+      {
+        UInt32 i;
+        reps[0] = (pos - LZMA_NUM_REPS);
+        for (i = 1; i < LZMA_NUM_REPS; i++)
+          reps[i] = prevOpt->backs[i - 1];
+      }
+    }
+    curOpt->state = (CState)state;
+
+    curOpt->backs[0] = reps[0];
+    curOpt->backs[1] = reps[1];
+    curOpt->backs[2] = reps[2];
+    curOpt->backs[3] = reps[3];
+
+    curPrice = curOpt->price;
+    nextIsChar = False;
+    data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
+    curByte = *data;
+    matchByte = *(data - (reps[0] + 1));
+
+    posState = (position & p->pbMask);
+
+    curAnd1Price = curPrice + GET_PRICE_0(p->isMatch[state][posState]);
+    {
+      const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
+      curAnd1Price +=
+        (!IsCharState(state) ?
+          LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) :
+          LitEnc_GetPrice(probs, curByte, p->ProbPrices));
+    }
+
+    nextOpt = &p->opt[cur + 1];
+
+    if (curAnd1Price < nextOpt->price)
+    {
+      nextOpt->price = curAnd1Price;
+      nextOpt->posPrev = cur;
+      MakeAsChar(nextOpt);
+      nextIsChar = True;
+    }
+
+    matchPrice = curPrice + GET_PRICE_1(p->isMatch[state][posState]);
+    repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]);
+    
+    if (matchByte == curByte && !(nextOpt->posPrev < cur && nextOpt->backPrev == 0))
+    {
+      UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, state, posState);
+      if (shortRepPrice <= nextOpt->price)
+      {
+        nextOpt->price = shortRepPrice;
+        nextOpt->posPrev = cur;
+        MakeAsShortRep(nextOpt);
+        nextIsChar = True;
+      }
+    }
+    numAvailFull = p->numAvail;
+    {
+      UInt32 temp = kNumOpts - 1 - cur;
+      if (temp < numAvailFull)
+        numAvailFull = temp;
+    }
+
+    if (numAvailFull < 2)
+      continue;
+    numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes);
+
+    if (!nextIsChar && matchByte != curByte) /* speed optimization */
+    {
+      /* try Literal + rep0 */
+      UInt32 temp;
+      UInt32 lenTest2;
+      const Byte *data2 = data - (reps[0] + 1);
+      UInt32 limit = p->numFastBytes + 1;
+      if (limit > numAvailFull)
+        limit = numAvailFull;
+
+      for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++);
+      lenTest2 = temp - 1;
+      if (lenTest2 >= 2)
+      {
+        UInt32 state2 = kLiteralNextStates[state];
+        UInt32 posStateNext = (position + 1) & p->pbMask;
+        UInt32 nextRepMatchPrice = curAnd1Price +
+            GET_PRICE_1(p->isMatch[state2][posStateNext]) +
+            GET_PRICE_1(p->isRep[state2]);
+        /* for (; lenTest2 >= 2; lenTest2--) */
+        {
+          UInt32 curAndLenPrice;
+          COptimal *opt;
+          UInt32 offset = cur + 1 + lenTest2;
+          while (lenEnd < offset)
+            p->opt[++lenEnd].price = kInfinityPrice;
+          curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);
+          opt = &p->opt[offset];
+          if (curAndLenPrice < opt->price)
+          {
+            opt->price = curAndLenPrice;
+            opt->posPrev = cur + 1;
+            opt->backPrev = 0;
+            opt->prev1IsChar = True;
+            opt->prev2 = False;
+          }
+        }
+      }
+    }
+    
+    startLen = 2; /* speed optimization */
+    {
+    UInt32 repIndex;
+    for (repIndex = 0; repIndex < LZMA_NUM_REPS; repIndex++)
+    {
+      UInt32 lenTest;
+      UInt32 lenTestTemp;
+      UInt32 price;
+      const Byte *data2 = data - (reps[repIndex] + 1);
+      if (data[0] != data2[0] || data[1] != data2[1])
+        continue;
+      for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++);
+      while (lenEnd < cur + lenTest)
+        p->opt[++lenEnd].price = kInfinityPrice;
+      lenTestTemp = lenTest;
+      price = repMatchPrice + GetPureRepPrice(p, repIndex, state, posState);
+      do
+      {
+        UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][lenTest - 2];
+        COptimal *opt = &p->opt[cur + lenTest];
+        if (curAndLenPrice < opt->price)
+        {
+          opt->price = curAndLenPrice;
+          opt->posPrev = cur;
+          opt->backPrev = repIndex;
+          opt->prev1IsChar = False;
+        }
+      }
+      while (--lenTest >= 2);
+      lenTest = lenTestTemp;
+      
+      if (repIndex == 0)
+        startLen = lenTest + 1;
+        
+      /* if (_maxMode) */
+        {
+          UInt32 lenTest2 = lenTest + 1;
+          UInt32 limit = lenTest2 + p->numFastBytes;
+          UInt32 nextRepMatchPrice;
+          if (limit > numAvailFull)
+            limit = numAvailFull;
+          for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);
+          lenTest2 -= lenTest + 1;
+          if (lenTest2 >= 2)
+          {
+            UInt32 state2 = kRepNextStates[state];
+            UInt32 posStateNext = (position + lenTest) & p->pbMask;
+            UInt32 curAndLenCharPrice =
+                price + p->repLenEnc.prices[posState][lenTest - 2] +
+                GET_PRICE_0(p->isMatch[state2][posStateNext]) +
+                LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]),
+                    data[lenTest], data2[lenTest], p->ProbPrices);
+            state2 = kLiteralNextStates[state2];
+            posStateNext = (position + lenTest + 1) & p->pbMask;
+            nextRepMatchPrice = curAndLenCharPrice +
+                GET_PRICE_1(p->isMatch[state2][posStateNext]) +
+                GET_PRICE_1(p->isRep[state2]);
+            
+            /* for (; lenTest2 >= 2; lenTest2--) */
+            {
+              UInt32 curAndLenPrice;
+              COptimal *opt;
+              UInt32 offset = cur + lenTest + 1 + lenTest2;
+              while (lenEnd < offset)
+                p->opt[++lenEnd].price = kInfinityPrice;
+              curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);
+              opt = &p->opt[offset];
+              if (curAndLenPrice < opt->price)
+              {
+                opt->price = curAndLenPrice;
+                opt->posPrev = cur + lenTest + 1;
+                opt->backPrev = 0;
+                opt->prev1IsChar = True;
+                opt->prev2 = True;
+                opt->posPrev2 = cur;
+                opt->backPrev2 = repIndex;
+              }
+            }
+          }
+        }
+    }
+    }
+    /* for (UInt32 lenTest = 2; lenTest <= newLen; lenTest++) */
+    if (newLen > numAvail)
+    {
+      newLen = numAvail;
+      for (numPairs = 0; newLen > matches[numPairs]; numPairs += 2);
+      matches[numPairs] = newLen;
+      numPairs += 2;
+    }
+    if (newLen >= startLen)
+    {
+      UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]);
+      UInt32 offs, curBack, posSlot;
+      UInt32 lenTest;
+      while (lenEnd < cur + newLen)
+        p->opt[++lenEnd].price = kInfinityPrice;
+
+      offs = 0;
+      while (startLen > matches[offs])
+        offs += 2;
+      curBack = matches[offs + 1];
+      GetPosSlot2(curBack, posSlot);
+      for (lenTest = /*2*/ startLen; ; lenTest++)
+      {
+        UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][lenTest - LZMA_MATCH_LEN_MIN];
+        UInt32 lenToPosState = GetLenToPosState(lenTest);
+        COptimal *opt;
+        if (curBack < kNumFullDistances)
+          curAndLenPrice += p->distancesPrices[lenToPosState][curBack];
+        else
+          curAndLenPrice += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[curBack & kAlignMask];
+        
+        opt = &p->opt[cur + lenTest];
+        if (curAndLenPrice < opt->price)
+        {
+          opt->price = curAndLenPrice;
+          opt->posPrev = cur;
+          opt->backPrev = curBack + LZMA_NUM_REPS;
+          opt->prev1IsChar = False;
+        }
+
+        if (/*_maxMode && */lenTest == matches[offs])
+        {
+          /* Try Match + Literal + Rep0 */
+          const Byte *data2 = data - (curBack + 1);
+          UInt32 lenTest2 = lenTest + 1;
+          UInt32 limit = lenTest2 + p->numFastBytes;
+          UInt32 nextRepMatchPrice;
+          if (limit > numAvailFull)
+            limit = numAvailFull;
+          for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);
+          lenTest2 -= lenTest + 1;
+          if (lenTest2 >= 2)
+          {
+            UInt32 state2 = kMatchNextStates[state];
+            UInt32 posStateNext = (position + lenTest) & p->pbMask;
+            UInt32 curAndLenCharPrice = curAndLenPrice +
+                GET_PRICE_0(p->isMatch[state2][posStateNext]) +
+                LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]),
+                    data[lenTest], data2[lenTest], p->ProbPrices);
+            state2 = kLiteralNextStates[state2];
+            posStateNext = (posStateNext + 1) & p->pbMask;
+            nextRepMatchPrice = curAndLenCharPrice +
+                GET_PRICE_1(p->isMatch[state2][posStateNext]) +
+                GET_PRICE_1(p->isRep[state2]);
+            
+            /* for (; lenTest2 >= 2; lenTest2--) */
+            {
+              UInt32 offset = cur + lenTest + 1 + lenTest2;
+              UInt32 curAndLenPrice;
+              COptimal *opt;
+              while (lenEnd < offset)
+                p->opt[++lenEnd].price = kInfinityPrice;
+              curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);
+              opt = &p->opt[offset];
+              if (curAndLenPrice < opt->price)
+              {
+                opt->price = curAndLenPrice;
+                opt->posPrev = cur + lenTest + 1;
+                opt->backPrev = 0;
+                opt->prev1IsChar = True;
+                opt->prev2 = True;
+                opt->posPrev2 = cur;
+                opt->backPrev2 = curBack + LZMA_NUM_REPS;
+              }
+            }
+          }
+          offs += 2;
+          if (offs == numPairs)
+            break;
+          curBack = matches[offs + 1];
+          if (curBack >= kNumFullDistances)
+            GetPosSlot2(curBack, posSlot);
+        }
+      }
+    }
+  }
+}
+
+#define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist))
+
+static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes)
+{
+  UInt32 numAvail, mainLen, mainDist, numPairs, repIndex, repLen, i;
+  const Byte *data;
+  const UInt32 *matches;
+
+  if (p->additionalOffset == 0)
+    mainLen = ReadMatchDistances(p, &numPairs);
+  else
+  {
+    mainLen = p->longestMatchLength;
+    numPairs = p->numPairs;
+  }
+
+  numAvail = p->numAvail;
+  *backRes = (UInt32)-1;
+  if (numAvail < 2)
+    return 1;
+  if (numAvail > LZMA_MATCH_LEN_MAX)
+    numAvail = LZMA_MATCH_LEN_MAX;
+  data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
+
+  repLen = repIndex = 0;
+  for (i = 0; i < LZMA_NUM_REPS; i++)
+  {
+    UInt32 len;
+    const Byte *data2 = data - (p->reps[i] + 1);
+    if (data[0] != data2[0] || data[1] != data2[1])
+      continue;
+    for (len = 2; len < numAvail && data[len] == data2[len]; len++);
+    if (len >= p->numFastBytes)
+    {
+      *backRes = i;
+      MovePos(p, len - 1);
+      return len;
+    }
+    if (len > repLen)
+    {
+      repIndex = i;
+      repLen = len;
+    }
+  }
+
+  matches = p->matches;
+  if (mainLen >= p->numFastBytes)
+  {
+    *backRes = matches[numPairs - 1] + LZMA_NUM_REPS;
+    MovePos(p, mainLen - 1);
+    return mainLen;
+  }
+
+  mainDist = 0; /* for GCC */
+  if (mainLen >= 2)
+  {
+    mainDist = matches[numPairs - 1];
+    while (numPairs > 2 && mainLen == matches[numPairs - 4] + 1)
+    {
+      if (!ChangePair(matches[numPairs - 3], mainDist))
+        break;
+      numPairs -= 2;
+      mainLen = matches[numPairs - 2];
+      mainDist = matches[numPairs - 1];
+    }
+    if (mainLen == 2 && mainDist >= 0x80)
+      mainLen = 1;
+  }
+
+  if (repLen >= 2 && (
+        (repLen + 1 >= mainLen) ||
+        (repLen + 2 >= mainLen && mainDist >= (1 << 9)) ||
+        (repLen + 3 >= mainLen && mainDist >= (1 << 15))))
+  {
+    *backRes = repIndex;
+    MovePos(p, repLen - 1);
+    return repLen;
+  }
+  
+  if (mainLen < 2 || numAvail <= 2)
+    return 1;
+
+  p->longestMatchLength = ReadMatchDistances(p, &p->numPairs);
+  if (p->longestMatchLength >= 2)
+  {
+    UInt32 newDistance = matches[p->numPairs - 1];
+    if ((p->longestMatchLength >= mainLen && newDistance < mainDist) ||
+        (p->longestMatchLength == mainLen + 1 && !ChangePair(mainDist, newDistance)) ||
+        (p->longestMatchLength > mainLen + 1) ||
+        (p->longestMatchLength + 1 >= mainLen && mainLen >= 3 && ChangePair(newDistance, mainDist)))
+      return 1;
+  }
+  
+  data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
+  for (i = 0; i < LZMA_NUM_REPS; i++)
+  {
+    UInt32 len, limit;
+    const Byte *data2 = data - (p->reps[i] + 1);
+    if (data[0] != data2[0] || data[1] != data2[1])
+      continue;
+    limit = mainLen - 1;
+    for (len = 2; len < limit && data[len] == data2[len]; len++);
+    if (len >= limit)
+      return 1;
+  }
+  *backRes = mainDist + LZMA_NUM_REPS;
+  MovePos(p, mainLen - 2);
+  return mainLen;
+}
+
+static void WriteEndMarker(CLzmaEnc *p, UInt32 posState)
+{
+  UInt32 len;
+  RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1);
+  RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0);
+  p->state = kMatchNextStates[p->state];
+  len = LZMA_MATCH_LEN_MIN;
+  LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);
+  RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, (1 << kNumPosSlotBits) - 1);
+  RangeEnc_EncodeDirectBits(&p->rc, (((UInt32)1 << 30) - 1) >> kNumAlignBits, 30 - kNumAlignBits);
+  RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask);
+}
+
+static SRes CheckErrors(CLzmaEnc *p)
+{
+  if (p->result != SZ_OK)
+    return p->result;
+  if (p->rc.res != SZ_OK)
+    p->result = SZ_ERROR_WRITE;
+  if (p->matchFinderBase.result != SZ_OK)
+    p->result = SZ_ERROR_READ;
+  if (p->result != SZ_OK)
+    p->finished = True;
+  return p->result;
+}
+
+static SRes Flush(CLzmaEnc *p, UInt32 nowPos)
+{
+  /* ReleaseMFStream(); */
+  p->finished = True;
+  if (p->writeEndMark)
+    WriteEndMarker(p, nowPos & p->pbMask);
+  RangeEnc_FlushData(&p->rc);
+  RangeEnc_FlushStream(&p->rc);
+  return CheckErrors(p);
+}
+
+static void FillAlignPrices(CLzmaEnc *p)
+{
+  UInt32 i;
+  for (i = 0; i < kAlignTableSize; i++)
+    p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices);
+  p->alignPriceCount = 0;
+}
+
+static void FillDistancesPrices(CLzmaEnc *p)
+{
+  UInt32 tempPrices[kNumFullDistances];
+  UInt32 i, lenToPosState;
+  for (i = kStartPosModelIndex; i < kNumFullDistances; i++)
+  {
+    UInt32 posSlot = GetPosSlot1(i);
+    UInt32 footerBits = ((posSlot >> 1) - 1);
+    UInt32 base = ((2 | (posSlot & 1)) << footerBits);
+    tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base - posSlot - 1, footerBits, i - base, p->ProbPrices);
+  }
+
+  for (lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++)
+  {
+    UInt32 posSlot;
+    const CLzmaProb *encoder = p->posSlotEncoder[lenToPosState];
+    UInt32 *posSlotPrices = p->posSlotPrices[lenToPosState];
+    for (posSlot = 0; posSlot < p->distTableSize; posSlot++)
+      posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices);
+    for (posSlot = kEndPosModelIndex; posSlot < p->distTableSize; posSlot++)
+      posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits);
+
+    {
+      UInt32 *distancesPrices = p->distancesPrices[lenToPosState];
+      UInt32 i;
+      for (i = 0; i < kStartPosModelIndex; i++)
+        distancesPrices[i] = posSlotPrices[i];
+      for (; i < kNumFullDistances; i++)
+        distancesPrices[i] = posSlotPrices[GetPosSlot1(i)] + tempPrices[i];
+    }
+  }
+  p->matchPriceCount = 0;
+}
+
+static void LzmaEnc_Construct(CLzmaEnc *p)
+{
+  RangeEnc_Construct(&p->rc);
+  MatchFinder_Construct(&p->matchFinderBase);
+  #ifndef _7ZIP_ST
+  MatchFinderMt_Construct(&p->matchFinderMt);
+  p->matchFinderMt.MatchFinder = &p->matchFinderBase;
+  #endif
+
+  {
+    CLzmaEncProps props;
+    LzmaEncProps_Init(&props);
+    LzmaEnc_SetProps(p, &props);
+  }
+
+  #ifndef LZMA_LOG_BSR
+  LzmaEnc_FastPosInit(p->g_FastPos);
+  #endif
+
+  LzmaEnc_InitPriceTables(p->ProbPrices);
+  p->litProbs = 0;
+  p->saveState.litProbs = 0;
+}
+
+CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc)
+{
+  void *p;
+  p = alloc->Alloc(alloc, sizeof(CLzmaEnc));
+  if (p != 0)
+    LzmaEnc_Construct((CLzmaEnc *)p);
+  return p;
+}
+
+static void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc)
+{
+  alloc->Free(alloc, p->litProbs);
+  alloc->Free(alloc, p->saveState.litProbs);
+  p->litProbs = 0;
+  p->saveState.litProbs = 0;
+}
+
+void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+  #ifndef _7ZIP_ST
+  MatchFinderMt_Destruct(&p->matchFinderMt, allocBig);
+  #endif
+  MatchFinder_Free(&p->matchFinderBase, allocBig);
+  LzmaEnc_FreeLits(p, alloc);
+  RangeEnc_Free(&p->rc, alloc);
+}
+
+void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+  LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig);
+  alloc->Free(alloc, p);
+}
+
+static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize, UInt32 maxUnpackSize)
+{
+  UInt32 nowPos32, startPos32;
+  if (p->needInit)
+  {
+    p->matchFinder.Init(p->matchFinderObj);
+    p->needInit = 0;
+  }
+
+  if (p->finished)
+    return p->result;
+  RINOK(CheckErrors(p));
+
+  nowPos32 = (UInt32)p->nowPos64;
+  startPos32 = nowPos32;
+
+  if (p->nowPos64 == 0)
+  {
+    UInt32 numPairs;
+    Byte curByte;
+    if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)
+      return Flush(p, nowPos32);
+    ReadMatchDistances(p, &numPairs);
+    RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][0], 0);
+    p->state = kLiteralNextStates[p->state];
+    curByte = p->matchFinder.GetIndexByte(p->matchFinderObj, 0 - p->additionalOffset);
+    LitEnc_Encode(&p->rc, p->litProbs, curByte);
+    p->additionalOffset--;
+    nowPos32++;
+  }
+
+  if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0)
+  for (;;)
+  {
+    UInt32 pos, len, posState;
+
+    if (p->fastMode)
+      len = GetOptimumFast(p, &pos);
+    else
+      len = GetOptimum(p, nowPos32, &pos);
+
+    #ifdef SHOW_STAT2
+    printf("\n pos = %4X,   len = %d   pos = %d", nowPos32, len, pos);
+    #endif
+
+    posState = nowPos32 & p->pbMask;
+    if (len == 1 && pos == (UInt32)-1)
+    {
+      Byte curByte;
+      CLzmaProb *probs;
+      const Byte *data;
+
+      RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 0);
+      data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
+      curByte = *data;
+      probs = LIT_PROBS(nowPos32, *(data - 1));
+      if (IsCharState(p->state))
+        LitEnc_Encode(&p->rc, probs, curByte);
+      else
+        LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0] - 1));
+      p->state = kLiteralNextStates[p->state];
+    }
+    else
+    {
+      RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1);
+      if (pos < LZMA_NUM_REPS)
+      {
+        RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 1);
+        if (pos == 0)
+        {
+          RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 0);
+          RangeEnc_EncodeBit(&p->rc, &p->isRep0Long[p->state][posState], ((len == 1) ? 0 : 1));
+        }
+        else
+        {
+          UInt32 distance = p->reps[pos];
+          RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 1);
+          if (pos == 1)
+            RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 0);
+          else
+          {
+            RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 1);
+            RangeEnc_EncodeBit(&p->rc, &p->isRepG2[p->state], pos - 2);
+            if (pos == 3)
+              p->reps[3] = p->reps[2];
+            p->reps[2] = p->reps[1];
+          }
+          p->reps[1] = p->reps[0];
+          p->reps[0] = distance;
+        }
+        if (len == 1)
+          p->state = kShortRepNextStates[p->state];
+        else
+        {
+          LenEnc_Encode2(&p->repLenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);
+          p->state = kRepNextStates[p->state];
+        }
+      }
+      else
+      {
+        UInt32 posSlot;
+        RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0);
+        p->state = kMatchNextStates[p->state];
+        LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);
+        pos -= LZMA_NUM_REPS;
+        GetPosSlot(pos, posSlot);
+        RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot);
+        
+        if (posSlot >= kStartPosModelIndex)
+        {
+          UInt32 footerBits = ((posSlot >> 1) - 1);
+          UInt32 base = ((2 | (posSlot & 1)) << footerBits);
+          UInt32 posReduced = pos - base;
+
+          if (posSlot < kEndPosModelIndex)
+            RcTree_ReverseEncode(&p->rc, p->posEncoders + base - posSlot - 1, footerBits, posReduced);
+          else
+          {
+            RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits);
+            RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask);
+            p->alignPriceCount++;
+          }
+        }
+        p->reps[3] = p->reps[2];
+        p->reps[2] = p->reps[1];
+        p->reps[1] = p->reps[0];
+        p->reps[0] = pos;
+        p->matchPriceCount++;
+      }
+    }
+    p->additionalOffset -= len;
+    nowPos32 += len;
+    if (p->additionalOffset == 0)
+    {
+      UInt32 processed;
+      if (!p->fastMode)
+      {
+        if (p->matchPriceCount >= (1 << 7))
+          FillDistancesPrices(p);
+        if (p->alignPriceCount >= kAlignTableSize)
+          FillAlignPrices(p);
+      }
+      if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)
+        break;
+      processed = nowPos32 - startPos32;
+      if (useLimits)
+      {
+        if (processed + kNumOpts + 300 >= maxUnpackSize ||
+            RangeEnc_GetProcessed(&p->rc) + kNumOpts * 2 >= maxPackSize)
+          break;
+      }
+      else if (processed >= (1 << 15))
+      {
+        p->nowPos64 += nowPos32 - startPos32;
+        return CheckErrors(p);
+      }
+    }
+  }
+  p->nowPos64 += nowPos32 - startPos32;
+  return Flush(p, nowPos32);
+}
+
+#define kBigHashDicLimit ((UInt32)1 << 24)
+
+static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+  UInt32 beforeSize = kNumOpts;
+  Bool btMode;
+  if (!RangeEnc_Alloc(&p->rc, alloc))
+    return SZ_ERROR_MEM;
+  btMode = (p->matchFinderBase.btMode != 0);
+  #ifndef _7ZIP_ST
+  p->mtMode = (p->multiThread && !p->fastMode && btMode);
+  #endif
+
+  {
+    unsigned lclp = p->lc + p->lp;
+    if (p->litProbs == 0 || p->saveState.litProbs == 0 || p->lclp != lclp)
+    {
+      LzmaEnc_FreeLits(p, alloc);
+      p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb));
+      p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb));
+      if (p->litProbs == 0 || p->saveState.litProbs == 0)
+      {
+        LzmaEnc_FreeLits(p, alloc);
+        return SZ_ERROR_MEM;
+      }
+      p->lclp = lclp;
+    }
+  }
+
+  p->matchFinderBase.bigHash = (p->dictSize > kBigHashDicLimit);
+
+  if (beforeSize + p->dictSize < keepWindowSize)
+    beforeSize = keepWindowSize - p->dictSize;
+
+  #ifndef _7ZIP_ST
+  if (p->mtMode)
+  {
+    RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig));
+    p->matchFinderObj = &p->matchFinderMt;
+    MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder);
+  }
+  else
+  #endif
+  {
+    if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig))
+      return SZ_ERROR_MEM;
+    p->matchFinderObj = &p->matchFinderBase;
+    MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder);
+  }
+  return SZ_OK;
+}
+
+void LzmaEnc_Init(CLzmaEnc *p)
+{
+  UInt32 i;
+  p->state = 0;
+  for (i = 0 ; i < LZMA_NUM_REPS; i++)
+    p->reps[i] = 0;
+
+  RangeEnc_Init(&p->rc);
+
+
+  for (i = 0; i < kNumStates; i++)
+  {
+    UInt32 j;
+    for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++)
+    {
+      p->isMatch[i][j] = kProbInitValue;
+      p->isRep0Long[i][j] = kProbInitValue;
+    }
+    p->isRep[i] = kProbInitValue;
+    p->isRepG0[i] = kProbInitValue;
+    p->isRepG1[i] = kProbInitValue;
+    p->isRepG2[i] = kProbInitValue;
+  }
+
+  {
+    UInt32 num = 0x300 << (p->lp + p->lc);
+    for (i = 0; i < num; i++)
+      p->litProbs[i] = kProbInitValue;
+  }
+
+  {
+    for (i = 0; i < kNumLenToPosStates; i++)
+    {
+      CLzmaProb *probs = p->posSlotEncoder[i];
+      UInt32 j;
+      for (j = 0; j < (1 << kNumPosSlotBits); j++)
+        probs[j] = kProbInitValue;
+    }
+  }
+  {
+    for (i = 0; i < kNumFullDistances - kEndPosModelIndex; i++)
+      p->posEncoders[i] = kProbInitValue;
+  }
+
+  LenEnc_Init(&p->lenEnc.p);
+  LenEnc_Init(&p->repLenEnc.p);
+
+  for (i = 0; i < (1 << kNumAlignBits); i++)
+    p->posAlignEncoder[i] = kProbInitValue;
+
+  p->optimumEndIndex = 0;
+  p->optimumCurrentIndex = 0;
+  p->additionalOffset = 0;
+
+  p->pbMask = (1 << p->pb) - 1;
+  p->lpMask = (1 << p->lp) - 1;
+}
+
+void LzmaEnc_InitPrices(CLzmaEnc *p)
+{
+  if (!p->fastMode)
+  {
+    FillDistancesPrices(p);
+    FillAlignPrices(p);
+  }
+
+  p->lenEnc.tableSize =
+  p->repLenEnc.tableSize =
+      p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN;
+  LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, p->ProbPrices);
+  LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, p->ProbPrices);
+}
+
+static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+  UInt32 i;
+  for (i = 0; i < (UInt32)kDicLogSizeMaxCompress; i++)
+    if (p->dictSize <= ((UInt32)1 << i))
+      break;
+  p->distTableSize = i * 2;
+
+  p->finished = False;
+  p->result = SZ_OK;
+  RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig));
+  LzmaEnc_Init(p);
+  LzmaEnc_InitPrices(p);
+  p->nowPos64 = 0;
+  return SZ_OK;
+}
+
+static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream,
+    ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+  CLzmaEnc *p = (CLzmaEnc *)pp;
+  p->matchFinderBase.stream = inStream;
+  p->needInit = 1;
+  p->rc.outStream = outStream;
+  return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig);
+}
+
+SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp,
+    ISeqInStream *inStream, UInt32 keepWindowSize,
+    ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+  CLzmaEnc *p = (CLzmaEnc *)pp;
+  p->matchFinderBase.stream = inStream;
+  p->needInit = 1;
+  return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
+}
+
+static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen)
+{
+  p->matchFinderBase.directInput = 1;
+  p->matchFinderBase.bufferBase = (Byte *)src;
+  p->matchFinderBase.directInputRem = srcLen;
+}
+
+SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,
+    UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+  CLzmaEnc *p = (CLzmaEnc *)pp;
+  LzmaEnc_SetInputBuf(p, src, srcLen);
+  p->needInit = 1;
+
+  return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
+}
+
+static void LzmaEnc_Finish(CLzmaEncHandle pp)
+{
+  #ifndef _7ZIP_ST
+  CLzmaEnc *p = (CLzmaEnc *)pp;
+  if (p->mtMode)
+    MatchFinderMt_ReleaseStream(&p->matchFinderMt);
+  #else
+  pp = pp;
+  #endif
+}
+
+typedef struct
+{
+  ISeqOutStream funcTable;
+  Byte *data;
+  SizeT rem;
+  Bool overflow;
+} CSeqOutStreamBuf;
+
+static size_t MyWrite(void *pp, const void *data, size_t size)
+{
+  CSeqOutStreamBuf *p = (CSeqOutStreamBuf *)pp;
+  if (p->rem < size)
+  {
+    size = p->rem;
+    p->overflow = True;
+  }
+  memcpy(p->data, data, size);
+  p->rem -= size;
+  p->data += size;
+  return size;
+}
+
+
+static UInt32 __maybe_unused LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp)
+{
+  const CLzmaEnc *p = (CLzmaEnc *)pp;
+  return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
+}
+
+const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp)
+{
+  const CLzmaEnc *p = (CLzmaEnc *)pp;
+  return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
+}
+
+static SRes __maybe_unused LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
+    Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize)
+{
+  CLzmaEnc *p = (CLzmaEnc *)pp;
+  UInt64 nowPos64;
+  SRes res;
+  CSeqOutStreamBuf outStream;
+
+  outStream.funcTable.Write = MyWrite;
+  outStream.data = dest;
+  outStream.rem = *destLen;
+  outStream.overflow = False;
+
+  p->writeEndMark = False;
+  p->finished = False;
+  p->result = SZ_OK;
+
+  if (reInit)
+    LzmaEnc_Init(p);
+  LzmaEnc_InitPrices(p);
+  nowPos64 = p->nowPos64;
+  RangeEnc_Init(&p->rc);
+  p->rc.outStream = &outStream.funcTable;
+
+  res = LzmaEnc_CodeOneBlock(p, True, desiredPackSize, *unpackSize);
+  
+  *unpackSize = (UInt32)(p->nowPos64 - nowPos64);
+  *destLen -= outStream.rem;
+  if (outStream.overflow)
+    return SZ_ERROR_OUTPUT_EOF;
+
+  return res;
+}
+
+static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress)
+{
+  SRes res = SZ_OK;
+
+  #ifndef _7ZIP_ST
+  Byte allocaDummy[0x300];
+  int i = 0;
+  for (i = 0; i < 16; i++)
+    allocaDummy[i] = (Byte)i;
+  #endif
+
+  for (;;)
+  {
+    res = LzmaEnc_CodeOneBlock(p, False, 0, 0);
+    if (res != SZ_OK || p->finished != 0)
+      break;
+    if (progress != 0)
+    {
+      res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc));
+      if (res != SZ_OK)
+      {
+        res = SZ_ERROR_PROGRESS;
+        break;
+      }
+    }
+  }
+  LzmaEnc_Finish(p);
+  return res;
+}
+
+SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress,
+    ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+  RINOK(LzmaEnc_Prepare(pp, outStream, inStream, alloc, allocBig));
+  return LzmaEnc_Encode2((CLzmaEnc *)pp, progress);
+}
+
+SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size)
+{
+  CLzmaEnc *p = (CLzmaEnc *)pp;
+  int i;
+  UInt32 dictSize = p->dictSize;
+  if (*size < LZMA_PROPS_SIZE)
+    return SZ_ERROR_PARAM;
+  *size = LZMA_PROPS_SIZE;
+  props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc);
+
+  for (i = 11; i <= 30; i++)
+  {
+    if (dictSize <= ((UInt32)2 << i))
+    {
+      dictSize = (2 << i);
+      break;
+    }
+    if (dictSize <= ((UInt32)3 << i))
+    {
+      dictSize = (3 << i);
+      break;
+    }
+  }
+
+  for (i = 0; i < 4; i++)
+    props[1 + i] = (Byte)(dictSize >> (8 * i));
+  return SZ_OK;
+}
+
+SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
+    int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+  SRes res;
+  CLzmaEnc *p = (CLzmaEnc *)pp;
+
+  CSeqOutStreamBuf outStream;
+
+  LzmaEnc_SetInputBuf(p, src, srcLen);
+
+  outStream.funcTable.Write = MyWrite;
+  outStream.data = dest;
+  outStream.rem = *destLen;
+  outStream.overflow = False;
+
+  p->writeEndMark = writeEndMark;
+
+  p->rc.outStream = &outStream.funcTable;
+  res = LzmaEnc_MemPrepare(pp, src, srcLen, 0, alloc, allocBig);
+  if (res == SZ_OK)
+    res = LzmaEnc_Encode2(p, progress);
+
+  *destLen -= outStream.rem;
+  if (outStream.overflow)
+    return SZ_ERROR_OUTPUT_EOF;
+  return res;
+}
+
+static __maybe_unused SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
+    const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
+    ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)
+{
+  CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc);
+  SRes res;
+  if (p == 0)
+    return SZ_ERROR_MEM;
+
+  res = LzmaEnc_SetProps(p, props);
+  if (res == SZ_OK)
+  {
+    res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize);
+    if (res == SZ_OK)
+      res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen,
+          writeEndMark, progress, alloc, allocBig);
+  }
+
+  LzmaEnc_Destroy(p, alloc, allocBig);
+  return res;
+}
diff --git a/lib/lzma/Makefile b/lib/lzma/Makefile
new file mode 100644
index 0000000..02e799c
--- /dev/null
+++ b/lib/lzma/Makefile
@@ -0,0 +1,7 @@
+lzma_compress-objs := LzFind.o LzmaEnc.o
+lzma_decompress-objs := LzmaDec.o
+
+obj-$(CONFIG_LZMA_COMPRESS) += lzma_compress.o
+obj-$(CONFIG_LZMA_DECOMPRESS) += lzma_decompress.o
+
+EXTRA_CFLAGS += -Iinclude/linux -Iinclude/linux/lzma -include types.h
diff --git a/lib/xz/xz_dec_stream.c b/lib/xz/xz_dec_stream.c
index ac809b1..9a60cc2 100644
--- a/lib/xz/xz_dec_stream.c
+++ b/lib/xz/xz_dec_stream.c
@@ -9,6 +9,7 @@
 
 #include "xz_private.h"
 #include "xz_stream.h"
+#include <linux/kernel.h>
 
 /* Hash used to validate the Index field */
 struct xz_dec_hash {
diff --git a/mm/bootmem.c b/mm/bootmem.c
index 0131170..d5ba3ac 100644
--- a/mm/bootmem.c
+++ b/mm/bootmem.c
@@ -15,6 +15,7 @@
 #include <linux/export.h>
 #include <linux/kmemleak.h>
 #include <linux/range.h>
+#include <linux/crashlog.h>
 #include <linux/memblock.h>
 
 #include <asm/bug.h>
@@ -177,6 +178,7 @@
 	if (!bdata->node_bootmem_map)
 		return 0;
 
+	crashlog_init_bootmem(bdata);
 	start = bdata->node_min_pfn;
 	end = bdata->node_low_pfn;
 
diff --git a/mm/memblock.c b/mm/memblock.c
index a44eab3..1bba9e6 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -19,6 +19,7 @@
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 #include <linux/memblock.h>
+#include <linux/crashlog.h>
 
 static struct memblock_region memblock_memory_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock;
 static struct memblock_region memblock_reserved_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock;
@@ -305,6 +306,8 @@
 	memblock_set_region_node(rgn, nid);
 	type->cnt++;
 	type->total_size += size;
+	if (type == &memblock.memory && idx == 0)
+		crashlog_init_memblock(base, size);
 }
 
 /**
diff --git a/mm/memory.c b/mm/memory.c
index 10b4dda..4dc26eb 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1412,6 +1412,7 @@
 	tlb_finish_mmu(&tlb, address, end);
 	return end;
 }
+EXPORT_SYMBOL_GPL(zap_page_range);
 
 /**
  * zap_vma_ptes - remove ptes mapping the vma
@@ -3087,6 +3088,7 @@
 	}
 	return 0;
 }
+EXPORT_SYMBOL_GPL(vmtruncate_range);
 
 /*
  * We enter with non-exclusive mmap_sem (to exclude vma changes,
diff --git a/mm/shmem.c b/mm/shmem.c
index 269d049..ca65160 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -2490,6 +2490,16 @@
 
 /* common code */
 
+void shmem_set_file(struct vm_area_struct *vma, struct file *file)
+{
+	if (vma->vm_file)
+		fput(vma->vm_file);
+	vma->vm_file = file;
+	vma->vm_ops = &shmem_vm_ops;
+	vma->vm_flags |= VM_CAN_NONLINEAR;
+}
+EXPORT_SYMBOL_GPL(shmem_set_file);
+
 /**
  * shmem_file_setup - get an unlinked file living in tmpfs
  * @name: name for dentry (to be seen in /proc/<pid>/maps
@@ -2567,11 +2577,8 @@
 	if (IS_ERR(file))
 		return PTR_ERR(file);
 
-	if (vma->vm_file)
-		fput(vma->vm_file);
-	vma->vm_file = file;
-	vma->vm_ops = &shmem_vm_ops;
-	vma->vm_flags |= VM_CAN_NONLINEAR;
+	shmem_set_file(vma, file);
+
 	return 0;
 }
 
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 86ce9a5..83cf23b 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -1257,6 +1257,7 @@
 	vunmap_page_range(addr, end);
 	flush_tlb_kernel_range(addr, end);
 }
+EXPORT_SYMBOL_GPL(unmap_kernel_range);
 
 int map_vm_area(struct vm_struct *area, pgprot_t prot, struct page ***pages)
 {
@@ -1394,6 +1395,7 @@
 	return __get_vm_area_node(size, 1, flags, VMALLOC_START, VMALLOC_END,
 				-1, GFP_KERNEL, __builtin_return_address(0));
 }
+EXPORT_SYMBOL_GPL(get_vm_area);
 
 struct vm_struct *get_vm_area_caller(unsigned long size, unsigned long flags,
 				void *caller)
diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c
index 4d39d80..b20b78d 100644
--- a/net/8021q/vlan_core.c
+++ b/net/8021q/vlan_core.c
@@ -102,8 +102,11 @@
 
 static struct sk_buff *vlan_reorder_header(struct sk_buff *skb)
 {
-	if (skb_cow(skb, skb_headroom(skb)) < 0)
+	if (skb_cow(skb, skb_headroom(skb)) < 0) {
+                kfree_skb(skb);
 		return NULL;
+	}
+
 	memmove(skb->data - ETH_HLEN, skb->data - VLAN_ETH_HLEN, 2 * ETH_ALEN);
 	skb->mac_header += VLAN_HLEN;
 	skb_reset_mac_len(skb);
diff --git a/net/Kconfig b/net/Kconfig
index e07272d..b3904e8 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -23,6 +23,12 @@
 
 if NET
 
+config ETHERNET_PACKET_MANGLE
+	bool
+	help
+	  This option can be selected by phy drivers that need to mangle
+	  packets going in or out of an ethernet device.
+
 config WANT_COMPAT_NETLINK_MESSAGES
 	bool
 	help
diff --git a/net/atm/br2684.c b/net/atm/br2684.c
index 353fccf..b57ae93 100644
--- a/net/atm/br2684.c
+++ b/net/atm/br2684.c
@@ -68,12 +68,15 @@
 	/* keep old push, pop functions for chaining */
 	void (*old_push)(struct atm_vcc *vcc, struct sk_buff *skb);
 	void (*old_pop)(struct atm_vcc *vcc, struct sk_buff *skb);
+	void (*old_release_cb)(struct atm_vcc *vcc);
+	struct module *old_owner;
 	enum br2684_encaps encaps;
 	struct list_head brvccs;
 #ifdef CONFIG_ATM_BR2684_IPFILTER
 	struct br2684_filter filter;
 #endif /* CONFIG_ATM_BR2684_IPFILTER */
 	unsigned copies_needed, copies_failed;
+	atomic_t qspace;
 };
 
 struct br2684_dev {
@@ -181,18 +184,15 @@
 static void br2684_pop(struct atm_vcc *vcc, struct sk_buff *skb)
 {
 	struct br2684_vcc *brvcc = BR2684_VCC(vcc);
-	struct net_device *net_dev = skb->dev;
 
-	pr_debug("(vcc %p ; net_dev %p )\n", vcc, net_dev);
+	pr_debug("(vcc %p ; net_dev %p )\n", vcc, brvcc->device);
 	brvcc->old_pop(vcc, skb);
 
-	if (!net_dev)
-		return;
-
-	if (atm_may_send(vcc, 0))
-		netif_wake_queue(net_dev);
-
+	/* If the queue space just went up from zero, wake */
+	if (atomic_inc_return(&brvcc->qspace) == 1)
+		netif_wake_queue(brvcc->device);
 }
+
 /*
  * Send a packet out a particular vcc.  Not to useful right now, but paves
  * the way for multiple vcc's per itf.  Returns true if we can send,
@@ -256,16 +256,30 @@
 	ATM_SKB(skb)->atm_options = atmvcc->atm_options;
 	dev->stats.tx_packets++;
 	dev->stats.tx_bytes += skb->len;
-	atmvcc->send(atmvcc, skb);
 
-	if (!atm_may_send(atmvcc, 0)) {
+	if (atomic_dec_return(&brvcc->qspace) < 1) {
+		/* No more please! */
 		netif_stop_queue(brvcc->device);
-		/*check for race with br2684_pop*/
-		if (atm_may_send(atmvcc, 0))
-			netif_start_queue(brvcc->device);
+		/* We might have raced with br2684_pop() */
+		if (unlikely(atomic_read(&brvcc->qspace) > 0))
+			netif_wake_queue(brvcc->device);
 	}
 
-	return 1;
+	/* If this fails immediately, the skb will be freed and br2684_pop()
+	   will wake the queue if appropriate. Just return an error so that
+	   the stats are updated correctly */
+	return !atmvcc->send(atmvcc, skb);
+}
+
+static void br2684_release_cb(struct atm_vcc *atmvcc)
+{
+	struct br2684_vcc *brvcc = BR2684_VCC(atmvcc);
+
+	if (atomic_read(&brvcc->qspace) > 0)
+		netif_wake_queue(brvcc->device);
+
+	if (brvcc->old_release_cb)
+		brvcc->old_release_cb(atmvcc);
 }
 
 static inline struct br2684_vcc *pick_outgoing_vcc(const struct sk_buff *skb,
@@ -279,6 +293,8 @@
 {
 	struct br2684_dev *brdev = BRPRIV(dev);
 	struct br2684_vcc *brvcc;
+	struct atm_vcc *atmvcc;
+	netdev_tx_t ret = NETDEV_TX_OK;
 
 	pr_debug("skb_dst(skb)=%p\n", skb_dst(skb));
 	read_lock(&devs_lock);
@@ -289,9 +305,26 @@
 		dev->stats.tx_carrier_errors++;
 		/* netif_stop_queue(dev); */
 		dev_kfree_skb(skb);
-		read_unlock(&devs_lock);
-		return NETDEV_TX_OK;
+		goto out_devs;
 	}
+	atmvcc = brvcc->atmvcc;
+
+	bh_lock_sock(sk_atm(atmvcc));
+
+	if (test_bit(ATM_VF_RELEASED, &atmvcc->flags) ||
+	    test_bit(ATM_VF_CLOSE, &atmvcc->flags) ||
+	    !test_bit(ATM_VF_READY, &atmvcc->flags)) {
+		dev->stats.tx_dropped++;
+		dev_kfree_skb(skb);
+		goto out;
+	}
+
+	if (sock_owned_by_user(sk_atm(atmvcc))) {
+		netif_stop_queue(brvcc->device);
+		ret = NETDEV_TX_BUSY;
+		goto out;
+	}
+
 	if (!br2684_xmit_vcc(skb, dev, brvcc)) {
 		/*
 		 * We should probably use netif_*_queue() here, but that
@@ -303,8 +336,11 @@
 		dev->stats.tx_errors++;
 		dev->stats.tx_fifo_errors++;
 	}
+ out:
+	bh_unlock_sock(sk_atm(atmvcc));
+ out_devs:
 	read_unlock(&devs_lock);
-	return NETDEV_TX_OK;
+	return ret;
 }
 
 /*
@@ -377,9 +413,10 @@
 	list_del(&brvcc->brvccs);
 	write_unlock_irq(&devs_lock);
 	brvcc->atmvcc->user_back = NULL;	/* what about vcc->recvq ??? */
+	brvcc->atmvcc->release_cb = brvcc->old_release_cb;
 	brvcc->old_push(brvcc->atmvcc, NULL);	/* pass on the bad news */
+	module_put(brvcc->old_owner);
 	kfree(brvcc);
-	module_put(THIS_MODULE);
 }
 
 /* when AAL5 PDU comes in: */
@@ -504,6 +541,13 @@
 	brvcc = kzalloc(sizeof(struct br2684_vcc), GFP_KERNEL);
 	if (!brvcc)
 		return -ENOMEM;
+	/*
+	 * Allow two packets in the ATM queue. One actually being sent, and one
+	 * for the ATM 'TX done' handler to send. It shouldn't take long to get
+	 * the next one from the netdev queue, when we need it. More than that
+	 * would be bufferbloat.
+	 */
+	atomic_set(&brvcc->qspace, 2);
 	write_lock_irq(&devs_lock);
 	net_dev = br2684_find_dev(&be.ifspec);
 	if (net_dev == NULL) {
@@ -546,9 +590,13 @@
 	brvcc->encaps = (enum br2684_encaps)be.encaps;
 	brvcc->old_push = atmvcc->push;
 	brvcc->old_pop = atmvcc->pop;
+	brvcc->old_release_cb = atmvcc->release_cb;
+	brvcc->old_owner = atmvcc->owner;
 	barrier();
 	atmvcc->push = br2684_push;
 	atmvcc->pop = br2684_pop;
+	atmvcc->release_cb = br2684_release_cb;
+	atmvcc->owner = THIS_MODULE;
 
 	/* initialize netdev carrier state */
 	if (atmvcc->dev->signal == ATM_PHY_SIG_LOST)
@@ -687,10 +735,13 @@
 			return -ENOIOCTLCMD;
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
-		if (cmd == ATM_SETBACKEND)
+		if (cmd == ATM_SETBACKEND) {
+			if (sock->state != SS_CONNECTED)
+				return -EINVAL;
 			return br2684_regvcc(atmvcc, argp);
-		else
+		} else {
 			return br2684_create(argp);
+		}
 #ifdef CONFIG_ATM_BR2684_IPFILTER
 	case BR2684_SETFILT:
 		if (atmvcc->push != br2684_push)
diff --git a/net/atm/common.c b/net/atm/common.c
index b4b44db..83a307d 100644
--- a/net/atm/common.c
+++ b/net/atm/common.c
@@ -126,10 +126,19 @@
 	rcu_read_unlock();
 }
 
+static void vcc_release_cb(struct sock *sk)
+{
+	struct atm_vcc *vcc = atm_sk(sk);
+
+	if (vcc->release_cb)
+		vcc->release_cb(vcc);
+}
+
 static struct proto vcc_proto = {
 	.name	  = "VCC",
 	.owner	  = THIS_MODULE,
 	.obj_size = sizeof(struct atm_vcc),
+	.release_cb = vcc_release_cb,
 };
 
 int vcc_create(struct net *net, struct socket *sock, int protocol, int family)
@@ -156,7 +165,9 @@
 	atomic_set(&sk->sk_rmem_alloc, 0);
 	vcc->push = NULL;
 	vcc->pop = NULL;
+	vcc->owner = NULL;
 	vcc->push_oam = NULL;
+	vcc->release_cb = NULL;
 	vcc->vpi = vcc->vci = 0; /* no VCI/VPI yet */
 	vcc->atm_options = vcc->aal_options = 0;
 	sk->sk_destruct = vcc_sock_destruct;
@@ -175,6 +186,7 @@
 			vcc->dev->ops->close(vcc);
 		if (vcc->push)
 			vcc->push(vcc, NULL); /* atmarpd has no push */
+		module_put(vcc->owner);
 
 		while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
 			atm_return(vcc, skb->truesize);
diff --git a/net/atm/pppoatm.c b/net/atm/pppoatm.c
index df35d9a..0fa3b71 100644
--- a/net/atm/pppoatm.c
+++ b/net/atm/pppoatm.c
@@ -60,14 +60,29 @@
 	struct atm_vcc	*atmvcc;	/* VCC descriptor */
 	void (*old_push)(struct atm_vcc *, struct sk_buff *);
 	void (*old_pop)(struct atm_vcc *, struct sk_buff *);
+	void (*old_release_cb)(struct atm_vcc *);
+	struct module *old_owner;
 					/* keep old push/pop for detaching */
 	enum pppoatm_encaps encaps;
+	atomic_t inflight;
+	unsigned long blocked;
 	int flags;			/* SC_COMP_PROT - compress protocol */
 	struct ppp_channel chan;	/* interface to generic ppp layer */
 	struct tasklet_struct wakeup_tasklet;
 };
 
 /*
+ * We want to allow two packets in the queue. The one that's currently in
+ * flight, and *one* queued up ready for the ATM device to send immediately
+ * from its TX done IRQ. We want to be able to use atomic_inc_not_zero(), so
+ * inflight == -2 represents an empty queue, -1 one packet, and zero means
+ * there are two packets in the queue.
+ */
+#define NONE_INFLIGHT -2
+
+#define BLOCKED 0
+
+/*
  * Header used for LLC Encapsulated PPP (4 bytes) followed by the LCP protocol
  * ID (0xC021) used in autodetection
  */
@@ -94,6 +109,24 @@
 	ppp_output_wakeup((struct ppp_channel *) arg);
 }
 
+static void pppoatm_release_cb(struct atm_vcc *atmvcc)
+{
+	struct pppoatm_vcc *pvcc = atmvcc_to_pvcc(atmvcc);
+
+	/*
+	 * As in pppoatm_pop(), it's safe to clear the BLOCKED bit here because
+	 * the wakeup *can't* race with pppoatm_send(). They both hold the PPP
+	 * channel's ->downl lock. And the potential race with *setting* it,
+	 * which leads to the double-check dance in pppoatm_may_send(), doesn't
+	 * exist here. In the sock_owned_by_user() case in pppoatm_send(), we
+	 * set the BLOCKED bit while the socket is still locked. We know that
+	 * ->release_cb() can't be called until that's done.
+	 */
+	if (test_and_clear_bit(BLOCKED, &pvcc->blocked))
+		tasklet_schedule(&pvcc->wakeup_tasklet);
+	if (pvcc->old_release_cb)
+		pvcc->old_release_cb(atmvcc);
+}
 /*
  * This gets called every time the ATM card has finished sending our
  * skb.  The ->old_pop will take care up normal atm flow control,
@@ -102,16 +135,30 @@
 static void pppoatm_pop(struct atm_vcc *atmvcc, struct sk_buff *skb)
 {
 	struct pppoatm_vcc *pvcc = atmvcc_to_pvcc(atmvcc);
+
 	pvcc->old_pop(atmvcc, skb);
+	atomic_dec(&pvcc->inflight);
+
 	/*
-	 * We don't really always want to do this since it's
-	 * really inefficient - it would be much better if we could
-	 * test if we had actually throttled the generic layer.
-	 * Unfortunately then there would be a nasty SMP race where
-	 * we could clear that flag just as we refuse another packet.
-	 * For now we do the safe thing.
+	 * We always used to run the wakeup tasklet unconditionally here, for
+	 * fear of race conditions where we clear the BLOCKED flag just as we
+	 * refuse another packet in pppoatm_send(). This was quite inefficient.
+	 *
+	 * In fact it's OK. The PPP core will only ever call pppoatm_send()
+	 * while holding the channel->downl lock. And ppp_output_wakeup() as
+	 * called by the tasklet will *also* grab that lock. So even if another
+	 * CPU is in pppoatm_send() right now, the tasklet isn't going to race
+	 * with it. The wakeup *will* happen after the other CPU is safely out
+	 * of pppoatm_send() again.
+	 *
+	 * So if the CPU in pppoatm_send() has already set the BLOCKED bit and
+	 * it about to return, that's fine. We trigger a wakeup which will
+	 * happen later. And if the CPU in pppoatm_send() *hasn't* set the
+	 * BLOCKED bit yet, that's fine too because of the double check in
+	 * pppoatm_may_send() which is commented there.
 	 */
-	tasklet_schedule(&pvcc->wakeup_tasklet);
+	if (test_and_clear_bit(BLOCKED, &pvcc->blocked))
+		tasklet_schedule(&pvcc->wakeup_tasklet);
 }
 
 /*
@@ -124,12 +171,11 @@
 	pvcc = atmvcc_to_pvcc(atmvcc);
 	atmvcc->push = pvcc->old_push;
 	atmvcc->pop = pvcc->old_pop;
+	atmvcc->release_cb = pvcc->old_release_cb;
 	tasklet_kill(&pvcc->wakeup_tasklet);
 	ppp_unregister_channel(&pvcc->chan);
 	atmvcc->user_back = NULL;
 	kfree(pvcc);
-	/* Gee, I hope we have the big kernel lock here... */
-	module_put(THIS_MODULE);
 }
 
 /* Called when an AAL5 PDU comes in */
@@ -138,9 +184,13 @@
 	struct pppoatm_vcc *pvcc = atmvcc_to_pvcc(atmvcc);
 	pr_debug("\n");
 	if (skb == NULL) {			/* VCC was closed */
+		struct module *module;
+
 		pr_debug("removing ATMPPP VCC %p\n", pvcc);
+		module = pvcc->old_owner;
 		pppoatm_unassign_vcc(atmvcc);
 		atmvcc->push(atmvcc, NULL);	/* Pass along bad news */
+		module_put(module);
 		return;
 	}
 	atm_return(atmvcc, skb->truesize);
@@ -184,6 +234,51 @@
 	ppp_input_error(&pvcc->chan, 0);
 }
 
+static int pppoatm_may_send(struct pppoatm_vcc *pvcc, int size)
+{
+	/*
+	 * It's not clear that we need to bother with using atm_may_send()
+	 * to check we don't exceed sk->sk_sndbuf. If userspace sets a
+	 * value of sk_sndbuf which is lower than the MTU, we're going to
+	 * block for ever. But the code always did that before we introduced
+	 * the packet count limit, so...
+	 */
+	if (atm_may_send(pvcc->atmvcc, size) &&
+	    atomic_inc_not_zero_hint(&pvcc->inflight, NONE_INFLIGHT))
+		return 1;
+
+	/*
+	 * We use test_and_set_bit() rather than set_bit() here because
+	 * we need to ensure there's a memory barrier after it. The bit
+	 * *must* be set before we do the atomic_inc() on pvcc->inflight.
+	 * There's no smp_mb__after_set_bit(), so it's this or abuse
+	 * smp_mb__after_clear_bit().
+	 */
+	test_and_set_bit(BLOCKED, &pvcc->blocked);
+
+	/*
+	 * We may have raced with pppoatm_pop(). If it ran for the
+	 * last packet in the queue, *just* before we set the BLOCKED
+	 * bit, then it might never run again and the channel could
+	 * remain permanently blocked. Cope with that race by checking
+	 * *again*. If it did run in that window, we'll have space on
+	 * the queue now and can return success. It's harmless to leave
+	 * the BLOCKED flag set, since it's only used as a trigger to
+	 * run the wakeup tasklet. Another wakeup will never hurt.
+	 * If pppoatm_pop() is running but hasn't got as far as making
+	 * space on the queue yet, then it hasn't checked the BLOCKED
+	 * flag yet either, so we're safe in that case too. It'll issue
+	 * an "immediate" wakeup... where "immediate" actually involves
+	 * taking the PPP channel's ->downl lock, which is held by the
+	 * code path that calls pppoatm_send(), and is thus going to
+	 * wait for us to finish.
+	 */
+	if (atm_may_send(pvcc->atmvcc, size) &&
+	    atomic_inc_not_zero(&pvcc->inflight))
+		return 1;
+
+	return 0;
+}
 /*
  * Called by the ppp_generic.c to send a packet - returns true if packet
  * was accepted.  If we return false, then it's our job to call
@@ -197,33 +292,59 @@
 static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb)
 {
 	struct pppoatm_vcc *pvcc = chan_to_pvcc(chan);
+	struct atm_vcc *vcc;
+	int ret;
+
 	ATM_SKB(skb)->vcc = pvcc->atmvcc;
 	pr_debug("(skb=0x%p, vcc=0x%p)\n", skb, pvcc->atmvcc);
 	if (skb->data[0] == '\0' && (pvcc->flags & SC_COMP_PROT))
 		(void) skb_pull(skb, 1);
+
+	vcc = ATM_SKB(skb)->vcc;
+	bh_lock_sock(sk_atm(vcc));
+	if (sock_owned_by_user(sk_atm(vcc))) {
+		/*
+		 * Needs to happen (and be flushed, hence test_and_) before we unlock
+		 * the socket. It needs to be seen by the time our ->release_cb gets
+		 * called.
+		 */
+		test_and_set_bit(BLOCKED, &pvcc->blocked);
+		goto nospace;
+	}
+	if (test_bit(ATM_VF_RELEASED, &vcc->flags) ||
+	    test_bit(ATM_VF_CLOSE, &vcc->flags) ||
+	    !test_bit(ATM_VF_READY, &vcc->flags)) {
+		bh_unlock_sock(sk_atm(vcc));
+		kfree_skb(skb);
+		return DROP_PACKET;
+	}
+
 	switch (pvcc->encaps) {		/* LLC encapsulation needed */
 	case e_llc:
 		if (skb_headroom(skb) < LLC_LEN) {
 			struct sk_buff *n;
 			n = skb_realloc_headroom(skb, LLC_LEN);
 			if (n != NULL &&
-			    !atm_may_send(pvcc->atmvcc, n->truesize)) {
+			    !pppoatm_may_send(pvcc, n->truesize)) {
 				kfree_skb(n);
 				goto nospace;
 			}
 			kfree_skb(skb);
 			skb = n;
-			if (skb == NULL)
+			if (skb == NULL) {
+				bh_unlock_sock(sk_atm(vcc));
 				return DROP_PACKET;
-		} else if (!atm_may_send(pvcc->atmvcc, skb->truesize))
+			}
+		} else if (!pppoatm_may_send(pvcc, skb->truesize))
 			goto nospace;
 		memcpy(skb_push(skb, LLC_LEN), pppllc, LLC_LEN);
 		break;
 	case e_vc:
-		if (!atm_may_send(pvcc->atmvcc, skb->truesize))
+		if (!pppoatm_may_send(pvcc, skb->truesize))
 			goto nospace;
 		break;
 	case e_autodetect:
+		bh_unlock_sock(sk_atm(vcc));
 		pr_debug("Trying to send without setting encaps!\n");
 		kfree_skb(skb);
 		return 1;
@@ -233,9 +354,12 @@
 	ATM_SKB(skb)->atm_options = ATM_SKB(skb)->vcc->atm_options;
 	pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n",
 		 skb, ATM_SKB(skb)->vcc, ATM_SKB(skb)->vcc->dev);
-	return ATM_SKB(skb)->vcc->send(ATM_SKB(skb)->vcc, skb)
+	ret = ATM_SKB(skb)->vcc->send(ATM_SKB(skb)->vcc, skb)
 	    ? DROP_PACKET : 1;
+	bh_unlock_sock(sk_atm(vcc));
+	return ret;
 nospace:
+	bh_unlock_sock(sk_atm(vcc));
 	/*
 	 * We don't have space to send this SKB now, but we might have
 	 * already applied SC_COMP_PROT compression, so may need to undo
@@ -285,8 +409,13 @@
 	if (pvcc == NULL)
 		return -ENOMEM;
 	pvcc->atmvcc = atmvcc;
+
+	/* Maximum is zero, so that we can use atomic_inc_not_zero() */
+	atomic_set(&pvcc->inflight, NONE_INFLIGHT);
 	pvcc->old_push = atmvcc->push;
 	pvcc->old_pop = atmvcc->pop;
+	pvcc->old_owner = atmvcc->owner;
+	pvcc->old_release_cb = atmvcc->release_cb;
 	pvcc->encaps = (enum pppoatm_encaps) be.encaps;
 	pvcc->chan.private = pvcc;
 	pvcc->chan.ops = &pppoatm_ops;
@@ -302,7 +431,9 @@
 	atmvcc->user_back = pvcc;
 	atmvcc->push = pppoatm_push;
 	atmvcc->pop = pppoatm_pop;
+	atmvcc->release_cb = pppoatm_release_cb;
 	__module_get(THIS_MODULE);
+	atmvcc->owner = THIS_MODULE;
 
 	/* re-process everything received between connection setup and
 	   backend setup */
@@ -331,6 +462,8 @@
 			return -ENOIOCTLCMD;
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
+		if (sock->state != SS_CONNECTED)
+			return -EINVAL;
 		return pppoatm_assign_vcc(atmvcc, argp);
 		}
 	case PPPIOCGCHAN:
diff --git a/net/bridge/Kconfig b/net/bridge/Kconfig
index 6dee7bf..9190ae4 100644
--- a/net/bridge/Kconfig
+++ b/net/bridge/Kconfig
@@ -6,7 +6,6 @@
 	tristate "802.1d Ethernet Bridging"
 	select LLC
 	select STP
-	depends on IPV6 || IPV6=n
 	---help---
 	  If you say Y here, then your Linux box will be able to act as an
 	  Ethernet bridge, which means that the different Ethernet segments it
diff --git a/net/bridge/br.c b/net/bridge/br.c
index ba780cc..9aa4c88 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -100,6 +100,10 @@
 	br_fdb_fini();
 }
 
+/* Hook for bridge event notifications */
+br_notify_hook_t __rcu *br_notify_hook __read_mostly;
+EXPORT_SYMBOL_GPL(br_notify_hook);
+
 module_init(br_init)
 module_exit(br_deinit)
 MODULE_LICENSE("GPL");
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 71773b0..41df49c 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -30,6 +30,8 @@
 	struct net_bridge_fdb_entry *dst;
 	struct net_bridge_mdb_entry *mdst;
 	struct br_cpu_netstats *brstats = this_cpu_ptr(br->stats);
+	struct net_bridge_port *pdst;
+	br_get_dst_hook_t *get_dst_hook;
 
 #ifdef CONFIG_BRIDGE_NETFILTER
 	if (skb->nf_bridge && (skb->nf_bridge->mask & BRNF_BRIDGED_DNAT)) {
@@ -49,9 +51,14 @@
 	skb_pull(skb, ETH_HLEN);
 
 	rcu_read_lock();
+	get_dst_hook = rcu_dereference(br_get_dst_hook);
 	if (is_broadcast_ether_addr(dest))
 		br_flood_deliver(br, skb);
 	else if (is_multicast_ether_addr(dest)) {
+		br_multicast_handle_hook_t *multicast_handle_hook = rcu_dereference(br_multicast_handle_hook);
+		if (!__br_get(multicast_handle_hook, true, NULL, skb))
+			goto out;
+
 		if (unlikely(netpoll_tx_running(dev))) {
 			br_flood_deliver(br, skb);
 			goto out;
@@ -66,6 +73,10 @@
 			br_multicast_deliver(mdst, skb);
 		else
 			br_flood_deliver(br, skb);
+	} else if ((pdst = __br_get(get_dst_hook, NULL, NULL, &skb))) {
+		if (!skb)
+			goto out;
+		br_deliver(pdst, skb);
 	} else if ((dst = __br_fdb_get(br, dest)) != NULL)
 		br_deliver(dst->dst, skb);
 	else
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index 5ba0c84..561ecf8 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -246,6 +246,7 @@
 
 	return NULL;
 }
+EXPORT_SYMBOL_GPL(__br_fdb_get);
 
 #if IS_ENABLED(CONFIG_ATM_LANE)
 /* Interface used by ATM LANE hook to test
@@ -453,6 +454,26 @@
 	}
 }
 
+/* Refresh FDB entries for bridge packets being forwarded by offload engines */
+void br_refresh_fdb_entry(struct net_device *dev, const char *addr)
+{
+	struct net_bridge_port *p = br_port_get_rcu(dev);
+
+	if (!p || p->state == BR_STATE_DISABLED)
+		return;
+
+	if (!is_valid_ether_addr(addr)) {
+		pr_info("bridge: Attempt to refresh with invalid ether address\n");
+		return;
+	}
+
+	rcu_read_lock();
+	br_fdb_update(p->br, p, addr);
+	rcu_read_unlock();
+}
+
+EXPORT_SYMBOL_GPL(br_refresh_fdb_entry);
+
 static int fdb_to_nud(const struct net_bridge_fdb_entry *fdb)
 {
 	if (fdb->is_local)
@@ -527,6 +548,7 @@
 		kfree_skb(skb);
 		goto errout;
 	}
+	__br_notify(RTNLGRP_NEIGH, type, fdb);
 	rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
 	return;
 errout:
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index 61f6534..8eee0f0 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -109,7 +109,7 @@
 /* called with rcu_read_lock */
 void br_forward(const struct net_bridge_port *to, struct sk_buff *skb, struct sk_buff *skb0)
 {
-	if (should_deliver(to, skb)) {
+	if (should_deliver(to, skb) && !(to->flags & BR_ISOLATE_MODE)) {
 		if (skb0)
 			deliver_clone(to, skb, __br_forward);
 		else
@@ -164,7 +164,8 @@
 static void br_flood(struct net_bridge *br, struct sk_buff *skb,
 		     struct sk_buff *skb0,
 		     void (*__packet_hook)(const struct net_bridge_port *p,
-					   struct sk_buff *skb))
+					   struct sk_buff *skb),
+		     bool forward)
 {
 	struct net_bridge_port *p;
 	struct net_bridge_port *prev;
@@ -172,6 +173,9 @@
 	prev = NULL;
 
 	list_for_each_entry_rcu(p, &br->port_list, list) {
+		if (forward && (p->flags & BR_ISOLATE_MODE))
+			continue;
+
 		prev = maybe_deliver(prev, p, skb, __packet_hook);
 		if (IS_ERR(prev))
 			goto out;
@@ -195,14 +199,14 @@
 /* called with rcu_read_lock */
 void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb)
 {
-	br_flood(br, skb, NULL, __br_deliver);
+	br_flood(br, skb, NULL, __br_deliver, false);
 }
 
 /* called under bridge lock */
 void br_flood_forward(struct net_bridge *br, struct sk_buff *skb,
 		      struct sk_buff *skb2)
 {
-	br_flood(br, skb, skb2, __br_forward);
+	br_flood(br, skb, skb2, __br_forward, true);
 }
 
 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
@@ -269,3 +273,6 @@
 	br_multicast_flood(mdst, skb, skb2, __br_forward);
 }
 #endif
+
+EXPORT_SYMBOL_GPL(br_deliver);
+EXPORT_SYMBOL_GPL(br_forward);
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 0a942fb..160275f 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -146,7 +146,6 @@
 	dev->priv_flags &= ~IFF_BRIDGE_PORT;
 
 	netdev_rx_handler_unregister(dev);
-	synchronize_net();
 
 	netdev_set_master(dev, NULL);
 
@@ -170,6 +169,8 @@
 		del_nbp(p);
 	}
 
+	br_fdb_delete_by_port(br, NULL, 1);
+
 	del_timer_sync(&br->gc_timer);
 
 	br_sysfs_delbr(br->dev);
@@ -454,3 +455,70 @@
 	rtnl_unlock();
 
 }
+
+/*
+ * br_port_dev_get()
+ *	Using the given addr, identify the port to which it is reachable,
+ * 	returing a reference to the net device associated with that port.
+ *
+ * NOTE: Return NULL if given dev is not a bridge or the mac has no associated port
+ */
+struct net_device *br_port_dev_get(struct net_device *dev, unsigned char *addr)
+{
+	struct net_bridge_fdb_entry *fdbe;
+	struct net_bridge *br;
+	struct net_device *pdev;
+
+	/*
+	 * Is this a bridge?
+	 */
+	if (!(dev->priv_flags & IFF_EBRIDGE)) {
+		return NULL;
+	}
+
+	/*
+	 * Lookup the fdb entry
+	 */
+	br = netdev_priv(dev);
+	rcu_read_lock();
+	fdbe = __br_fdb_get(br, addr);
+	if (!fdbe) {
+		rcu_read_unlock();
+		return NULL;
+	}
+
+	/*
+	 * Get reference to the port dev
+	 */
+	pdev = fdbe->dst->dev;
+	dev_hold(pdev);
+	rcu_read_unlock();
+
+	return pdev;
+}
+EXPORT_SYMBOL_GPL(br_port_dev_get);
+
+/* Update bridge statistics for bridge packets processed by offload engines */
+void br_dev_update_stats(struct net_device *dev, struct rtnl_link_stats64 *nlstats)
+{
+	struct net_bridge *br;
+	struct br_cpu_netstats *stats;
+
+	/*
+	 * Is this a bridge?
+	 */
+	if (!(dev->priv_flags & IFF_EBRIDGE)) {
+		return;
+	}
+
+	br = netdev_priv(dev);
+	stats = per_cpu_ptr(br->stats, 0);
+
+	u64_stats_update_begin(&stats->syncp);
+	stats->rx_packets += nlstats->rx_packets;
+	stats->rx_bytes += nlstats->rx_bytes;
+	stats->tx_packets += nlstats->tx_packets;
+	stats->tx_bytes += nlstats->tx_bytes;
+	u64_stats_update_end(&stats->syncp);
+}
+EXPORT_SYMBOL_GPL(br_dev_update_stats);
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 5a31731..5ca9e1b 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -26,6 +26,14 @@
 br_should_route_hook_t __rcu *br_should_route_hook __read_mostly;
 EXPORT_SYMBOL(br_should_route_hook);
 
+/* Hook for external Multicast handler */
+br_multicast_handle_hook_t __rcu *br_multicast_handle_hook __read_mostly;
+EXPORT_SYMBOL_GPL(br_multicast_handle_hook);
+
+/* Hook for external forwarding logic */
+br_get_dst_hook_t __rcu *br_get_dst_hook __read_mostly;
+EXPORT_SYMBOL_GPL(br_get_dst_hook);
+
 static int br_pass_frame_up(struct sk_buff *skb)
 {
 	struct net_device *indev, *brdev = BR_INPUT_SKB_CB(skb)->brdev;
@@ -53,6 +61,8 @@
 	struct net_bridge_fdb_entry *dst;
 	struct net_bridge_mdb_entry *mdst;
 	struct sk_buff *skb2;
+	struct net_bridge_port *pdst = NULL;
+	br_get_dst_hook_t *get_dst_hook = rcu_dereference(br_get_dst_hook);
 
 	if (!p || p->state == BR_STATE_DISABLED)
 		goto drop;
@@ -65,7 +75,7 @@
 	    br_multicast_rcv(br, p, skb))
 		goto drop;
 
-	if (p->state == BR_STATE_LEARNING)
+	if ((p->state == BR_STATE_LEARNING) && skb->protocol != htons(ETH_P_PAE))
 		goto drop;
 
 	BR_INPUT_SKB_CB(skb)->brdev = br->dev;
@@ -78,9 +88,17 @@
 
 	dst = NULL;
 
-	if (is_broadcast_ether_addr(dest))
+	if (skb->protocol == htons(ETH_P_PAE)) {
+		skb2 = skb;
+		/* Do not forward 802.1x/EAP frames */
+		skb = NULL;
+	} else if (is_broadcast_ether_addr(dest))
 		skb2 = skb;
 	else if (is_multicast_ether_addr(dest)) {
+		br_multicast_handle_hook_t *multicast_handle_hook = rcu_dereference(br_multicast_handle_hook);
+		if (!__br_get(multicast_handle_hook, true, p, skb))
+			goto out;
+
 		mdst = br_mdb_get(br, skb);
 		if (mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) {
 			if ((mdst && mdst->mglist) ||
@@ -94,7 +112,10 @@
 			skb2 = skb;
 
 		br->dev->stats.multicast++;
-	} else if ((dst = __br_fdb_get(br, dest)) && dst->is_local) {
+	} else if ((pdst = __br_get(get_dst_hook, NULL, p, &skb))) {
+		if (!skb) goto out;
+	} else if ((p->flags & BR_ISOLATE_MODE) ||
+		   ((dst = __br_fdb_get(br, dest)) && dst->is_local)) {
 		skb2 = skb;
 		/* Do not forward the packet since it's local. */
 		skb = NULL;
@@ -103,8 +124,12 @@
 	if (skb) {
 		if (dst) {
 			dst->used = jiffies;
-			br_forward(dst->dst, skb, skb2);
-		} else
+			pdst = dst->dst;
+		}
+
+		if (pdst)
+			br_forward(pdst, skb, skb2);
+		else
 			br_flood_forward(br, skb, skb2);
 	}
 
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index a1daf82..1fca3a2 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -104,6 +104,7 @@
 		kfree_skb(skb);
 		goto errout;
 	}
+	__br_notify(RTNLGRP_LINK, event, port);
 	rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC);
 	return;
 errout:
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index e1d8822..9d25894 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -18,6 +18,7 @@
 #include <linux/netpoll.h>
 #include <linux/u64_stats_sync.h>
 #include <net/route.h>
+#include <linux/export.h>
 
 #define BR_HASH_BITS 8
 #define BR_HASH_SIZE (1 << BR_HASH_BITS)
@@ -135,6 +136,7 @@
 
 	unsigned long 			flags;
 #define BR_HAIRPIN_MODE		0x00000001
+#define BR_ISOLATE_MODE		0x00000002
 
 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
 	u32				multicast_startup_queries_sent;
@@ -158,8 +160,7 @@
 
 static inline struct net_bridge_port *br_port_get_rcu(const struct net_device *dev)
 {
-	struct net_bridge_port *port = rcu_dereference(dev->rx_handler_data);
-	return br_port_exists(dev) ? port : NULL;
+	return rcu_dereference(dev->rx_handler_data);
 }
 
 static inline struct net_bridge_port *br_port_get_rtnl(struct net_device *dev)
@@ -560,4 +561,15 @@
 #define br_sysfs_delbr(dev)	do { } while(0)
 #endif /* CONFIG_SYSFS */
 
+#define __br_get( __hook, __default, __args ... ) \
+		(__hook ? (__hook( __args )) : (__default))
+
+static inline void __br_notify(int group, int type, const void *data)
+{
+	br_notify_hook_t *notify_hook = rcu_dereference(br_notify_hook);
+
+	if (notify_hook)
+		notify_hook(group, type, data);
+}
+
 #endif
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
index 6229b62..cde52fe 100644
--- a/net/bridge/br_sysfs_if.c
+++ b/net/bridge/br_sysfs_if.c
@@ -149,6 +149,22 @@
 static BRPORT_ATTR(hairpin_mode, S_IRUGO | S_IWUSR,
 		   show_hairpin_mode, store_hairpin_mode);
 
+static ssize_t show_isolate_mode(struct net_bridge_port *p, char *buf)
+{
+	int isolate_mode = (p->flags & BR_ISOLATE_MODE) ? 1 : 0;
+	return sprintf(buf, "%d\n", isolate_mode);
+}
+static ssize_t store_isolate_mode(struct net_bridge_port *p, unsigned long v)
+{
+	if (v)
+		p->flags |= BR_ISOLATE_MODE;
+	else
+		p->flags &= ~BR_ISOLATE_MODE;
+	return 0;
+}
+static BRPORT_ATTR(isolate_mode, S_IRUGO | S_IWUSR,
+		   show_isolate_mode, store_isolate_mode);
+
 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
 static ssize_t show_multicast_router(struct net_bridge_port *p, char *buf)
 {
@@ -181,6 +197,7 @@
 	&brport_attr_hold_timer,
 	&brport_attr_flush,
 	&brport_attr_hairpin_mode,
+	&brport_attr_isolate_mode,
 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
 	&brport_attr_multicast_router,
 #endif
diff --git a/net/core/dev.c b/net/core/dev.c
index 0336374..d7d90ba 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1176,6 +1176,7 @@
 		net_dmaengine_get();
 		dev_set_rx_mode(dev);
 		dev_activate(dev);
+		add_device_randomness(dev->dev_addr, dev->addr_len);
 	}
 
 	return ret;
@@ -2227,8 +2228,14 @@
 		if (dev->priv_flags & IFF_XMIT_DST_RELEASE)
 			skb_dst_drop(skb);
 
-		if (!list_empty(&ptype_all))
-			dev_queue_xmit_nit(skb, dev);
+		/*
+		 * If this skb has been fast forwarded then we don't want it to
+		 * go to any taps (by definition we're trying to bypass them).
+		 */
+		if (unlikely(!skb->fast_forwarded)) {
+			if (!list_empty(&ptype_all))
+				dev_queue_xmit_nit(skb, dev);
+		}
 
 		skb_orphan_try(skb);
 
@@ -2266,9 +2273,19 @@
 			}
 		}
 
-		skb_len = skb->len;
-		rc = ops->ndo_start_xmit(skb, dev);
-		trace_net_dev_xmit(skb, rc, dev, skb_len);
+#ifdef CONFIG_ETHERNET_PACKET_MANGLE
+		if (!dev->eth_mangle_tx ||
+		    (skb = dev->eth_mangle_tx(dev, skb)) != NULL)
+#else
+		if (1)
+#endif
+		{
+			skb_len = skb->len;
+			rc = ops->ndo_start_xmit(skb, dev);
+			trace_net_dev_xmit(skb, rc, dev, skb_len);
+		} else {
+			rc = NETDEV_TX_OK;
+		}
 		if (rc == NETDEV_TX_OK)
 			txq_trans_update(txq);
 		return rc;
@@ -2288,9 +2305,19 @@
 		if (dev->priv_flags & IFF_XMIT_DST_RELEASE)
 			skb_dst_drop(nskb);
 
-		skb_len = nskb->len;
-		rc = ops->ndo_start_xmit(nskb, dev);
-		trace_net_dev_xmit(nskb, rc, dev, skb_len);
+#ifdef CONFIG_ETHERNET_PACKET_MANGLE
+		if (!dev->eth_mangle_tx ||
+		    (nskb = dev->eth_mangle_tx(dev, nskb)) != NULL)
+#else
+		if (1)
+#endif
+		{
+			skb_len = nskb->len;
+			rc = ops->ndo_start_xmit(nskb, dev);
+			trace_net_dev_xmit(nskb, rc, dev, skb_len);
+		} else {
+			rc = NETDEV_TX_OK;
+		}
 		if (unlikely(rc != NETDEV_TX_OK)) {
 			if (rc & ~NETDEV_TX_MASK)
 				goto out_kfree_gso_skb;
@@ -3158,6 +3185,7 @@
 	if (dev->rx_handler)
 		return -EBUSY;
 
+	/* Note: rx_handler_data must be set before rx_handler */
 	rcu_assign_pointer(dev->rx_handler_data, rx_handler_data);
 	rcu_assign_pointer(dev->rx_handler, rx_handler);
 
@@ -3178,10 +3206,18 @@
 
 	ASSERT_RTNL();
 	RCU_INIT_POINTER(dev->rx_handler, NULL);
+	/* a reader seeing a non NULL rx_handler in a rcu_read_lock()
+	 * section has a guarantee to see a non NULL rx_handler_data
+	 * as well.
+	 */
+	synchronize_net();
 	RCU_INIT_POINTER(dev->rx_handler_data, NULL);
 }
 EXPORT_SYMBOL_GPL(netdev_rx_handler_unregister);
 
+int (*athrs_fast_nat_recv)(struct sk_buff *skb) __rcu __read_mostly;
+EXPORT_SYMBOL_GPL(athrs_fast_nat_recv);
+
 static int __netif_receive_skb(struct sk_buff *skb)
 {
 	struct packet_type *ptype, *pt_prev;
@@ -3191,6 +3227,7 @@
 	bool deliver_exact = false;
 	int ret = NET_RX_DROP;
 	__be16 type;
+	int (*fast_recv)(struct sk_buff *skb);
 
 	net_timestamp_check(!netdev_tstamp_prequeue, skb);
 
@@ -3208,10 +3245,10 @@
 	skb_reset_transport_header(skb);
 	skb_reset_mac_len(skb);
 
-	pt_prev = NULL;
-
 	rcu_read_lock();
 
+	pt_prev = NULL;
+
 another_round:
 
 	__this_cpu_inc(softnet_data.processed);
@@ -3222,6 +3259,14 @@
 			goto out;
 	}
 
+	fast_recv = rcu_dereference(athrs_fast_nat_recv);
+	if (fast_recv) {
+		if (fast_recv(skb)) {
+			rcu_read_unlock();
+			return NET_RX_SUCCESS;
+		}
+	}
+
 #ifdef CONFIG_NET_CLS_ACT
 	if (skb->tc_verd & TC_NCLS) {
 		skb->tc_verd = CLR_TC_NCLS(skb->tc_verd);
@@ -3730,9 +3775,8 @@
 #endif
 	napi->weight = weight_p;
 	local_irq_disable();
-	while (work < quota) {
+	while (1) {
 		struct sk_buff *skb;
-		unsigned int qlen;
 
 		while ((skb = __skb_dequeue(&sd->process_queue))) {
 			local_irq_enable();
@@ -3746,24 +3790,25 @@
 		}
 
 		rps_lock(sd);
-		qlen = skb_queue_len(&sd->input_pkt_queue);
-		if (qlen)
-			skb_queue_splice_tail_init(&sd->input_pkt_queue,
-						   &sd->process_queue);
 
-		if (qlen < quota - work) {
+		if (skb_queue_empty(&sd->input_pkt_queue)) {
 			/*
 			 * Inline a custom version of __napi_complete().
 			 * only current cpu owns and manipulates this napi,
-			 * and NAPI_STATE_SCHED is the only possible flag set on backlog.
-			 * we can use a plain write instead of clear_bit(),
+			 * and NAPI_STATE_SCHED is the only possible flag set
+			 * on backlog.
+                         * We can use a plain write instead of clear_bit(),
 			 * and we dont need an smp_mb() memory barrier.
 			 */
 			list_del(&napi->poll_list);
 			napi->state = 0;
+			rps_unlock(sd);
 
-			quota = work + qlen;
+			break;
 		}
+
+		skb_queue_splice_tail_init(&sd->input_pkt_queue,
+                                           &sd->process_queue);
 		rps_unlock(sd);
 	}
 	local_irq_enable();
@@ -4823,6 +4868,7 @@
 	err = ops->ndo_set_mac_address(dev, sa);
 	if (!err)
 		call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
+	add_device_randomness(dev->dev_addr, dev->addr_len);
 	return err;
 }
 EXPORT_SYMBOL(dev_set_mac_address);
@@ -5602,6 +5648,7 @@
 	dev_init_scheduler(dev);
 	dev_hold(dev);
 	list_netdevice(dev);
+	add_device_randomness(dev->dev_addr, dev->addr_len);
 
 	/* Notify protocols, that a new device appeared. */
 	ret = call_netdevice_notifiers(NETDEV_REGISTER, dev);
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 5c30296..2e6bb2c 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1371,6 +1371,7 @@
 			goto errout;
 		send_addr_notify = 1;
 		modified = 1;
+		add_device_randomness(dev->dev_addr, dev->addr_len);
 	}
 
 	if (tb[IFLA_MTU]) {
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 38f49e0..a88a97a 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -58,6 +58,7 @@
 #include <linux/scatterlist.h>
 #include <linux/errqueue.h>
 #include <linux/prefetch.h>
+#include <linux/if.h>
 
 #include <net/protocol.h>
 #include <net/dst.h>
@@ -320,6 +321,22 @@
 }
 EXPORT_SYMBOL(__netdev_alloc_skb);
 
+struct sk_buff *__netdev_alloc_skb_ip_align(struct net_device *dev,
+		unsigned int length, gfp_t gfp)
+{
+	struct sk_buff *skb = __netdev_alloc_skb(dev, length + NET_IP_ALIGN, gfp);
+
+#ifdef CONFIG_ETHERNET_PACKET_MANGLE
+	if (dev->priv_flags & IFF_NO_IP_ALIGN)
+		return skb;
+#endif
+
+	if (NET_IP_ALIGN && skb)
+		skb_reserve(skb, NET_IP_ALIGN);
+	return skb;
+}
+EXPORT_SYMBOL(__netdev_alloc_skb_ip_align);
+
 void skb_add_rx_frag(struct sk_buff *skb, int i, struct page *page, int off,
 		int size)
 {
diff --git a/net/core/sock.c b/net/core/sock.c
index 02f8dfe..e5b38c6 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -2138,6 +2138,10 @@
 	spin_lock_bh(&sk->sk_lock.slock);
 	if (sk->sk_backlog.tail)
 		__release_sock(sk);
+
+	if (sk->sk_prot->release_cb)
+		sk->sk_prot->release_cb(sk);
+
 	sk->sk_lock.owned = 0;
 	if (waitqueue_active(&sk->sk_lock.wq))
 		wake_up(&sk->sk_lock.wq);
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c
index a246836..c2af070 100644
--- a/net/ethernet/eth.c
+++ b/net/ethernet/eth.c
@@ -160,6 +160,12 @@
 	struct ethhdr *eth;
 
 	skb->dev = dev;
+
+#ifdef CONFIG_ETHERNET_PACKET_MANGLE
+	if (dev->eth_mangle_rx)
+		dev->eth_mangle_rx(dev, skb);
+#endif
+
 	skb_reset_mac_header(skb);
 	skb_pull_inline(skb, ETH_HLEN);
 	eth = eth_hdr(skb);
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 7bc2db6..066e3f1 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -2,6 +2,7 @@
  *	IP multicast routing support for mrouted 3.6/3.8
  *
  *		(c) 1995 Alan Cox, <alan@lxorguk.ukuu.org.uk>
+ *              Copyright (c) 2013 The Linux Foundation. All rights reserved.
  *	  Linux Consultancy and Custom Driver Development
  *
  *	This program is free software; you can redistribute it and/or
@@ -982,7 +983,7 @@
 	if (!found) {
 		/* Create a new entry if allowable */
 
-		if (atomic_read(&mrt->cache_resolve_queue_len) >= 10 ||
+		if (atomic_read(&mrt->cache_resolve_queue_len) >= sysctl_igmp_max_memberships ||
 		    (c = ipmr_cache_alloc_unres()) == NULL) {
 			spin_unlock_bh(&mfc_unres_lock);
 
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 24e556e..70a21fe 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -81,9 +81,14 @@
 
 #define FWINV(bool, invflg) ((bool) ^ !!(ipinfo->invflags & (invflg)))
 
-	if (FWINV((ip->saddr&ipinfo->smsk.s_addr) != ipinfo->src.s_addr,
+	if (ipinfo->flags & IPT_F_NO_DEF_MATCH)
+		return true;
+
+	if (FWINV(ipinfo->smsk.s_addr &&
+		  (ip->saddr&ipinfo->smsk.s_addr) != ipinfo->src.s_addr,
 		  IPT_INV_SRCIP) ||
-	    FWINV((ip->daddr&ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr,
+	    FWINV(ipinfo->dmsk.s_addr &&
+		  (ip->daddr&ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr,
 		  IPT_INV_DSTIP)) {
 		dprintf("Source or dest mismatch.\n");
 
@@ -134,6 +139,29 @@
 	return true;
 }
 
+static void
+ip_checkdefault(struct ipt_ip *ip)
+{
+	static const char iface_mask[IFNAMSIZ] = {};
+
+	if (ip->invflags || ip->flags & IPT_F_FRAG)
+		return;
+
+	if (memcmp(ip->iniface_mask, iface_mask, IFNAMSIZ) != 0)
+		return;
+
+	if (memcmp(ip->outiface_mask, iface_mask, IFNAMSIZ) != 0)
+		return;
+
+	if (ip->smsk.s_addr || ip->dmsk.s_addr)
+		return;
+
+	if (ip->proto)
+		return;
+
+	ip->flags |= IPT_F_NO_DEF_MATCH;
+}
+
 static bool
 ip_checkentry(const struct ipt_ip *ip)
 {
@@ -284,6 +312,33 @@
 	return (void *)entry + entry->next_offset;
 }
 
+static bool
+ipt_handle_default_rule(struct ipt_entry *e, unsigned int *verdict)
+{
+	struct xt_entry_target *t;
+	struct xt_standard_target *st;
+
+	if (e->target_offset != sizeof(struct ipt_entry))
+		return false;
+
+	if (!(e->ip.flags & IPT_F_NO_DEF_MATCH))
+		return false;
+
+	t = ipt_get_target(e);
+	if (t->u.kernel.target->target)
+		return false;
+
+	st = (struct xt_standard_target *) t;
+	if (st->verdict == XT_RETURN)
+		return false;
+
+	if (st->verdict >= 0)
+		return false;
+
+	*verdict = (unsigned)(-st->verdict) - 1;
+	return true;
+}
+
 /* Returns one of the generic firewall policies, like NF_ACCEPT. */
 unsigned int
 ipt_do_table(struct sk_buff *skb,
@@ -308,6 +363,25 @@
 	ip = ip_hdr(skb);
 	indev = in ? in->name : nulldevname;
 	outdev = out ? out->name : nulldevname;
+
+	IP_NF_ASSERT(table->valid_hooks & (1 << hook));
+	local_bh_disable();
+	addend = xt_write_recseq_begin();
+	private = table->private;
+	cpu        = smp_processor_id();
+	table_base = private->entries[cpu];
+	jumpstack  = (struct ipt_entry **)private->jumpstack[cpu];
+	stackptr   = per_cpu_ptr(private->stackptr, cpu);
+	origptr    = *stackptr;
+
+	e = get_entry(table_base, private->hook_entry[hook]);
+	if (ipt_handle_default_rule(e, &verdict)) {
+		ADD_COUNTER(e->counters, skb->len, 1);
+		xt_write_recseq_end(addend);
+		local_bh_enable();
+		return verdict;
+	}
+
 	/* We handle fragments by dealing with the first fragment as
 	 * if it was a normal packet.  All other fragments are treated
 	 * normally, except that they will NEVER match rules that ask
@@ -322,18 +396,6 @@
 	acpar.family  = NFPROTO_IPV4;
 	acpar.hooknum = hook;
 
-	IP_NF_ASSERT(table->valid_hooks & (1 << hook));
-	local_bh_disable();
-	addend = xt_write_recseq_begin();
-	private = table->private;
-	cpu        = smp_processor_id();
-	table_base = private->entries[cpu];
-	jumpstack  = (struct ipt_entry **)private->jumpstack[cpu];
-	stackptr   = per_cpu_ptr(private->stackptr, cpu);
-	origptr    = *stackptr;
-
-	e = get_entry(table_base, private->hook_entry[hook]);
-
 	pr_debug("Entering %s(hook %u); sp at %u (UF %p)\n",
 		 table->name, hook, origptr,
 		 get_entry(table_base, private->underflow[hook]));
@@ -561,7 +623,7 @@
 }
 
 static int
-check_entry(const struct ipt_entry *e, const char *name)
+check_entry(struct ipt_entry *e, const char *name)
 {
 	const struct xt_entry_target *t;
 
@@ -570,6 +632,8 @@
 		return -EINVAL;
 	}
 
+	ip_checkdefault(&e->ip);
+
 	if (e->target_offset + sizeof(struct xt_entry_target) >
 	    e->next_offset)
 		return -EINVAL;
@@ -931,6 +995,7 @@
 	const struct xt_table_info *private = table->private;
 	int ret = 0;
 	const void *loc_cpu_entry;
+	u8 flags;
 
 	counters = alloc_counters(table);
 	if (IS_ERR(counters))
@@ -962,6 +1027,14 @@
 			goto free_counters;
 		}
 
+		flags = e->ip.flags & IPT_F_MASK;
+		if (copy_to_user(userptr + off
+				 + offsetof(struct ipt_entry, ip.flags),
+				 &flags, sizeof(flags)) != 0) {
+			ret = -EFAULT;
+			goto free_counters;
+		}
+
 		for (i = sizeof(struct ipt_entry);
 		     i < e->target_offset;
 		     i += m->u.match_size) {
diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c
index d0319f9..c592b49 100644
--- a/net/ipv4/netfilter/nf_nat_sip.c
+++ b/net/ipv4/netfilter/nf_nat_sip.c
@@ -4,6 +4,7 @@
  * based on RR's ip_nat_ftp.c and other modules.
  * (C) 2007 United Security Providers
  * (C) 2007, 2008 Patrick McHardy <kaber@trash.net>
+ * Copyright (c) 2013 The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -73,19 +74,25 @@
 	enum ip_conntrack_info ctinfo;
 	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
 	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+	struct nf_conn_help *help = nfct_help(ct);
 	char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
 	unsigned int buflen;
 	__be32 newaddr;
 	__be16 newport;
 
-	if (ct->tuplehash[dir].tuple.src.u3.ip == addr->ip &&
-	    ct->tuplehash[dir].tuple.src.u.udp.port == port) {
+	if (ct->tuplehash[dir].tuple.src.u3.ip == addr->ip) {
 		newaddr = ct->tuplehash[!dir].tuple.dst.u3.ip;
-		newport = ct->tuplehash[!dir].tuple.dst.u.udp.port;
-	} else if (ct->tuplehash[dir].tuple.dst.u3.ip == addr->ip &&
-		   ct->tuplehash[dir].tuple.dst.u.udp.port == port) {
+		if(ct->tuplehash[dir].tuple.src.u.udp.port == port)
+			newport = ct->tuplehash[!dir].tuple.dst.u.udp.port;
+		else
+			newport = ct->tuplehash[dir].tuple.src.u.udp.port;
+	} else if (ct->tuplehash[dir].tuple.dst.u3.ip == addr->ip ) {
 		newaddr = ct->tuplehash[!dir].tuple.src.u3.ip;
-		newport = ct->tuplehash[!dir].tuple.src.u.udp.port;
+		if(ct->tuplehash[dir].tuple.dst.u.udp.port == port)
+			newport = help->help.ct_sip_info.forced_dport ? :
+			  ct->tuplehash[!dir].tuple.src.u.udp.port;
+		else
+			newport = ct->tuplehash[dir].tuple.dst.u.udp.port;
 	} else
 		return 1;
 
@@ -121,6 +128,7 @@
 	enum ip_conntrack_info ctinfo;
 	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
 	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+	struct nf_conn_help *help = nfct_help(ct);
 	unsigned int coff, matchoff, matchlen;
 	enum sip_header_types hdr;
 	union nf_inet_addr addr;
@@ -152,14 +160,12 @@
 		char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
 
 		/* We're only interested in headers related to this
-		 * connection */
+		 * host,support VIA info port different with session source port*/
 		if (request) {
-			if (addr.ip != ct->tuplehash[dir].tuple.src.u3.ip ||
-			    port != ct->tuplehash[dir].tuple.src.u.udp.port)
+			if (addr.ip != ct->tuplehash[dir].tuple.src.u3.ip )
 				goto next;
 		} else {
-			if (addr.ip != ct->tuplehash[dir].tuple.dst.u3.ip ||
-			    port != ct->tuplehash[dir].tuple.dst.u.udp.port)
+			if (addr.ip != ct->tuplehash[dir].tuple.dst.u3.ip)
 				goto next;
 		}
 
@@ -229,6 +235,20 @@
 	    !map_sip_addr(skb, dataoff, dptr, datalen, SIP_HDR_TO))
 		return NF_DROP;
 
+	/* Mangle destination port for Cisco phones, then fix up checksums */
+	if (dir == IP_CT_DIR_REPLY && help->help.ct_sip_info.forced_dport) {
+		struct udphdr *uh;
+
+		if (!skb_make_writable(skb, skb->len))
+			return NF_DROP;
+
+		uh = (struct udphdr *)(skb->data + ip_hdrlen(skb));
+		uh->dest = help->help.ct_sip_info.forced_dport;
+
+		if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo, 0, 0, NULL, 0))
+			return NF_DROP;
+	}
+
 	return NF_ACCEPT;
 }
 
@@ -280,8 +300,10 @@
 	enum ip_conntrack_info ctinfo;
 	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
 	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+	struct nf_conn_help *help = nfct_help(ct);
 	__be32 newip;
 	u_int16_t port;
+	__be16 srcport;
 	char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
 	unsigned buflen;
 
@@ -294,8 +316,9 @@
 	/* If the signalling port matches the connection's source port in the
 	 * original direction, try to use the destination port in the opposite
 	 * direction. */
-	if (exp->tuple.dst.u.udp.port ==
-	    ct->tuplehash[dir].tuple.src.u.udp.port)
+	srcport = help->help.ct_sip_info.forced_dport ? :
+		  ct->tuplehash[dir].tuple.src.u.udp.port;
+	if (exp->tuple.dst.u.udp.port == srcport)
 		port = ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.port);
 	else
 		port = ntohs(exp->tuple.dst.u.udp.port);
@@ -464,6 +487,7 @@
 	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
 	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
 	u_int16_t port;
+	int portloop = 0;
 
 	/* Connection will come from reply */
 	if (ct->tuplehash[dir].tuple.src.u3.ip ==
@@ -486,8 +510,13 @@
 
 	/* Try to get same pair of ports: if not, try to change them. */
 	for (port = ntohs(rtp_exp->tuple.dst.u.udp.port);
-	     port != 0; port += 2) {
+	     port != 0 || 0 == portloop; port += 2) {
 		int ret;
+		/* support edge case port 65534/65535 */
+		if(0 == port) {
+			portloop = 1;
+			port +=	2;
+		}
 
 		rtp_exp->tuple.dst.u.udp.port = htons(port);
 		ret = nf_ct_expect_related(rtp_exp);
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile
index 686934a..049f35e 100644
--- a/net/ipv6/Makefile
+++ b/net/ipv6/Makefile
@@ -40,3 +40,4 @@
 obj-y += addrconf_core.o exthdrs_core.o
 
 obj-$(subst m,y,$(CONFIG_IPV6)) += inet6_hashtables.o
+obj-$(subst m,y,$(CONFIG_IPV6)) += inet6_stubs.o
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 6b8ebc5..e034d48 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1103,7 +1103,7 @@
 	return ret;
 }
 
-int ipv6_dev_get_saddr(struct net *net, struct net_device *dst_dev,
+static int __ipv6_dev_get_saddr(struct net *net, struct net_device *dst_dev,
 		       const struct in6_addr *daddr, unsigned int prefs,
 		       struct in6_addr *saddr)
 {
@@ -1228,7 +1228,6 @@
 	in6_ifa_put(hiscore->ifa);
 	return 0;
 }
-EXPORT_SYMBOL(ipv6_dev_get_saddr);
 
 int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr,
 		    unsigned char banned_flags)
@@ -4840,6 +4839,9 @@
 
 	ipv6_addr_label_rtnl_register();
 
+	BUG_ON(ipv6_dev_get_saddr_hook != NULL);
+	rcu_assign_pointer(ipv6_dev_get_saddr_hook, __ipv6_dev_get_saddr);
+
 	return 0;
 errout:
 	rtnl_af_unregister(&inet6_ops);
@@ -4858,6 +4860,9 @@
 	struct net_device *dev;
 	int i;
 
+	rcu_assign_pointer(ipv6_dev_get_saddr_hook, NULL);
+	synchronize_rcu();
+
 	unregister_netdevice_notifier(&ipv6_dev_notf);
 	unregister_pernet_subsys(&addrconf_ops);
 	ipv6_addr_label_cleanup();
diff --git a/net/ipv6/inet6_stubs.c b/net/ipv6/inet6_stubs.c
new file mode 100644
index 0000000..c9a90e7
--- /dev/null
+++ b/net/ipv6/inet6_stubs.c
@@ -0,0 +1,33 @@
+/*
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the 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/export.h>
+#include <net/ipv6.h>
+
+int (*ipv6_dev_get_saddr_hook)(struct net *net, struct net_device *dev,
+			const struct in6_addr *daddr, unsigned int srcprefs,
+			struct in6_addr *saddr);
+
+EXPORT_SYMBOL(ipv6_dev_get_saddr_hook);
+
+int ipv6_dev_get_saddr(struct net *net, struct net_device *dst_dev,
+			const struct in6_addr *daddr, unsigned int prefs,
+			struct in6_addr *saddr)
+{
+	int ret = -EADDRNOTAVAIL;
+	typeof(ipv6_dev_get_saddr_hook) dev_get_saddr;
+
+	rcu_read_lock();
+	dev_get_saddr = rcu_dereference(ipv6_dev_get_saddr_hook);
+
+	if (dev_get_saddr)
+		ret = dev_get_saddr(net, dst_dev, daddr, prefs, saddr);
+
+	rcu_read_unlock();
+	return ret;
+}
+EXPORT_SYMBOL(ipv6_dev_get_saddr);
+
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index f8ac4ef..673cdbf 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -2,7 +2,7 @@
 	depends on NET && INET && NETFILTER
 
 config NETFILTER_NETLINK
-	tristate
+	tristate "Netfilter NFNETLINK interface"
 
 config NETFILTER_NETLINK_ACCT
 tristate "Netfilter NFACCT over NFNETLINK interface"
@@ -103,6 +103,14 @@
 
 	  If unsure, say `N'.
 
+config NF_CONNTRACK_CHAIN_EVENTS
+	bool "Register multiple callbacks to ct events"
+	depends on NF_CONNTRACK_EVENTS
+	help
+	  Support multiple registrations.
+
+	  If unsure, say `N'.
+
 config NF_CONNTRACK_TIMESTAMP
 	bool  'Connection tracking timestamping'
 	depends on NETFILTER_ADVANCED
@@ -181,7 +189,6 @@
 
 config NF_CONNTRACK_H323
 	tristate "H.323 protocol support"
-	depends on (IPV6 || IPV6=n)
 	depends on NETFILTER_ADVANCED
 	help
 	  H.323 is a VoIP signalling protocol from ITU-T. As one of the most
@@ -627,7 +634,6 @@
 
 config NETFILTER_XT_TARGET_TCPMSS
 	tristate '"TCPMSS" target support'
-	depends on (IPV6 || IPV6=n)
 	default m if NETFILTER_ADVANCED=n
 	---help---
 	  This option adds a `TCPMSS' target, which allows you to alter the
@@ -859,6 +865,27 @@
 
 	  If unsure, say N.
 
+config NETFILTER_XT_MATCH_LAYER7
+	tristate '"layer7" match support'
+	depends on EXPERIMENTAL
+	depends on NETFILTER_XTABLES
+	depends on NETFILTER_ADVANCED
+	depends on NF_CONNTRACK
+	help
+	  Say Y if you want to be able to classify connections (and their
+	  packets) based on regular expression matching of their application
+	  layer data.   This is one way to classify applications such as
+	  peer-to-peer filesharing systems that do not always use the same
+	  port.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
+config NETFILTER_XT_MATCH_LAYER7_DEBUG
+	bool 'Layer 7 debugging output'
+	depends on NETFILTER_XT_MATCH_LAYER7
+	help
+	  Say Y to get lots of debugging output.
+
 config NETFILTER_XT_MATCH_LENGTH
 	tristate '"length" match support'
 	depends on NETFILTER_ADVANCED
@@ -1055,6 +1082,12 @@
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+config NETFILTER_XT_MATCH_LAYER7_DEBUG
+	bool 'Layer 7 debugging output'
+	depends on NETFILTER_XT_MATCH_LAYER7
+	help
+	  Say Y to get lots of debugging output.
+
 config NETFILTER_XT_MATCH_STATISTIC
 	tristate '"statistic" match support'
 	depends on NETFILTER_ADVANCED
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 40f4c3d..9bf8a00 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -105,6 +105,7 @@
 obj-$(CONFIG_NETFILTER_XT_MATCH_SCTP) += xt_sctp.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_SOCKET) += xt_socket.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_STATE) += xt_state.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_LAYER7) += xt_layer7.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_STATISTIC) += xt_statistic.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += xt_tcpmss.o
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index fa4b82c..ad29bb4 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -214,6 +214,14 @@
 	 * too. */
 	nf_ct_remove_expectations(ct);
 
+	#if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE)
+	if(ct->layer7.app_proto)
+		kfree(ct->layer7.app_proto);
+	if(ct->layer7.app_data)
+	kfree(ct->layer7.app_data);
+	#endif
+
+
 	/* We overload first tuple to link into unconfirmed list. */
 	if (!nf_ct_is_confirmed(ct)) {
 		BUG_ON(hlist_nulls_unhashed(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode));
diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c
index 14af632..878e4bb 100644
--- a/net/netfilter/nf_conntrack_ecache.c
+++ b/net/netfilter/nf_conntrack_ecache.c
@@ -16,6 +16,9 @@
 #include <linux/stddef.h>
 #include <linux/err.h>
 #include <linux/percpu.h>
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+#include <linux/notifier.h>
+#endif
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
 #include <linux/slab.h>
@@ -25,6 +28,11 @@
 #include <net/netfilter/nf_conntrack_core.h>
 #include <net/netfilter/nf_conntrack_extend.h>
 
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+ATOMIC_NOTIFIER_HEAD(nf_conntrack_chain);
+EXPORT_SYMBOL_GPL(nf_conntrack_chain);
+#endif
+
 static DEFINE_MUTEX(nf_ct_ecache_mutex);
 
 /* deliver cached events and clear cache entry - must be called with locally
@@ -33,13 +41,15 @@
 {
 	struct net *net = nf_ct_net(ct);
 	unsigned long events;
-	struct nf_ct_event_notifier *notify;
 	struct nf_conntrack_ecache *e;
+#ifndef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+	struct nf_ct_event_notifier *notify;
 
 	rcu_read_lock();
 	notify = rcu_dereference(net->ct.nf_conntrack_event_cb);
 	if (notify == NULL)
 		goto out_unlock;
+#endif
 
 	e = nf_ct_ecache_find(ct);
 	if (e == NULL)
@@ -53,12 +63,18 @@
 			.pid	= 0,
 			.report	= 0
 		};
-		int ret;
 		/* We make a copy of the missed event cache without taking
 		 * the lock, thus we may send missed events twice. However,
 		 * this does not harm and it happens very rarely. */
 		unsigned long missed = e->missed;
 
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+		atomic_notifier_call_chain(&nf_conntrack_chain,
+                               events | missed,
+                               &item);
+#else
+		int ret;
+
 		if (!((events | missed) & e->ctmask))
 			goto out_unlock;
 
@@ -71,13 +87,24 @@
 				e->missed &= ~missed;
 			spin_unlock_bh(&ct->lock);
 		} 
+#endif
 	}
 
 out_unlock:
+#ifndef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
 	rcu_read_unlock();
+#else
+	return;
+#endif
 }
 EXPORT_SYMBOL_GPL(nf_ct_deliver_cached_events);
 
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+int nf_conntrack_register_notifier(struct net *net, struct notifier_block *nb)
+{
+	return atomic_notifier_chain_register(&nf_conntrack_chain, nb);
+}
+#else
 int nf_conntrack_register_notifier(struct net *net,
 				   struct nf_ct_event_notifier *new)
 {
@@ -99,8 +126,15 @@
 	mutex_unlock(&nf_ct_ecache_mutex);
 	return ret;
 }
+#endif
 EXPORT_SYMBOL_GPL(nf_conntrack_register_notifier);
 
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+int nf_conntrack_unregister_notifier(struct net *net, struct notifier_block *nb)
+{
+	return atomic_notifier_chain_unregister(&nf_conntrack_chain, nb);
+}
+#else
 void nf_conntrack_unregister_notifier(struct net *net,
 				      struct nf_ct_event_notifier *new)
 {
@@ -113,6 +147,7 @@
 	RCU_INIT_POINTER(net->ct.nf_conntrack_event_cb, NULL);
 	mutex_unlock(&nf_ct_ecache_mutex);
 }
+#endif
 EXPORT_SYMBOL_GPL(nf_conntrack_unregister_notifier);
 
 int nf_ct_expect_register_notifier(struct net *net,
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index b49da6c..4e6e77c 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -28,6 +28,9 @@
 #include <linux/netlink.h>
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+#include <linux/notifier.h>
+#endif
 #include <linux/slab.h>
 
 #include <linux/netfilter.h>
@@ -553,13 +556,21 @@
 	       ;
 }
 
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+static int ctnetlink_conntrack_event(struct notifier_block *this,
+                           unsigned long events, void *ptr)
+#else
 static int
 ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item)
+#endif
 {
 	struct net *net;
 	struct nlmsghdr *nlh;
 	struct nfgenmsg *nfmsg;
 	struct nlattr *nest_parms;
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+	struct nf_ct_event *item = (struct nf_ct_event *)ptr;
+#endif
 	struct nf_conn *ct = item->ct;
 	struct sk_buff *skb;
 	unsigned int type;
@@ -2112,9 +2123,15 @@
 }
 
 #ifdef CONFIG_NF_CONNTRACK_EVENTS
+#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+static struct notifier_block ctnl_notifier = {
+	.notifier_call = ctnetlink_conntrack_event,
+};
+#else
 static struct nf_ct_event_notifier ctnl_notifier = {
 	.fcn = ctnetlink_conntrack_event,
 };
+#endif
 
 static struct nf_exp_event_notifier ctnl_notifier_exp = {
 	.fcn = ctnetlink_expect_event,
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index 97b9f3e..97f710a 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -29,10 +29,15 @@
 #include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
 #include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
 
+/* Do not check the TCP window for incoming packets  */
+int nf_ct_tcp_no_window_check __read_mostly = 0;
+EXPORT_SYMBOL_GPL(nf_ct_tcp_no_window_check);
+
 /* "Be conservative in what you do,
     be liberal in what you accept from others."
     If it's non-zero, we mark only out of window RST segments as INVALID. */
-static int nf_ct_tcp_be_liberal __read_mostly = 0;
+int nf_ct_tcp_be_liberal __read_mostly = 0;
+EXPORT_SYMBOL_GPL(nf_ct_tcp_be_liberal);
 
 /* If it is set to zero, we disable picking up already established
    connections. */
@@ -524,6 +529,9 @@
 	s16 receiver_offset;
 	bool res;
 
+	if (nf_ct_tcp_no_window_check)
+		return true;
+
 	/*
 	 * Get the required data from the packet.
 	 */
@@ -1321,6 +1329,13 @@
 		.proc_handler	= proc_dointvec,
 	},
 	{
+		.procname       = "nf_conntrack_tcp_no_window_check",
+		.data           = &nf_ct_tcp_no_window_check,
+		.maxlen         = sizeof(unsigned int),
+		.mode           = 0644,
+		.proc_handler   = proc_dointvec,
+	},
+	{
 		.procname       = "nf_conntrack_tcp_be_liberal",
 		.data           = &nf_ct_tcp_be_liberal,
 		.maxlen         = sizeof(unsigned int),
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
index 93faf6a..4f108f7 100644
--- a/net/netfilter/nf_conntrack_sip.c
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -1363,8 +1363,25 @@
 {
 	enum ip_conntrack_info ctinfo;
 	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
+	struct nf_conn_help *help = nfct_help(ct);
+	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
 	unsigned int matchoff, matchlen;
 	unsigned int cseq, i;
+	union nf_inet_addr addr;
+	__be16 port;
+
+	/* Many Cisco IP phones use a high source port for SIP requests, but
+	 * listen for the response on port 5060.  If we are the local
+	 * router for one of these phones, save the port number from the
+	 * Via: header so that nf_nat_sip can redirect the responses to
+	 * the correct port.
+	 */
+	if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen,
+				    SIP_HDR_VIA_UDP, NULL, &matchoff,
+				    &matchlen, &addr, &port) > 0 &&
+	    port != ct->tuplehash[dir].tuple.src.u.udp.port &&
+	    nf_inet_addr_cmp(&addr, &ct->tuplehash[dir].tuple.src.u3))
+		help->help.ct_sip_info.forced_dport = port;
 
 	for (i = 0; i < ARRAY_SIZE(sip_handlers); i++) {
 		const struct sip_handler *handler;
@@ -1468,7 +1485,7 @@
 
 		msglen = origlen = end - dptr;
 		if (msglen > datalen)
-			return NF_DROP;
+			return NF_ACCEPT;
 
 		ret = process_sip_msg(skb, ct, dataoff, &dptr, &msglen);
 		if (ret != NF_ACCEPT)
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 885f5ab..da2a66e 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -239,6 +239,12 @@
 	if (ct_show_delta_time(s, ct))
 		goto release;
 
+#if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE)
+	if(ct->layer7.app_proto &&
+           seq_printf(s, "l7proto=%s ", ct->layer7.app_proto))
+		return -ENOSPC;
+#endif
+
 	if (seq_printf(s, "use=%u\n", atomic_read(&ct->ct_general.use)))
 		goto release;
 
@@ -261,10 +267,34 @@
 			sizeof(struct ct_iter_state));
 }
 
+static int kill_all(struct nf_conn *i, void *data)
+{
+    return 1;
+}
+
+static ssize_t ct_file_write(struct file *file, const char __user *buf,
+			     size_t count, loff_t *ppos)
+{
+	struct seq_file *seq = file->private_data;
+	struct net *net = seq_file_net(seq);
+
+	if (count) {
+		char c;
+
+		if (get_user(c, buf))
+			return -EFAULT;
+
+		if (c == 'f')
+			nf_ct_iterate_cleanup(net, kill_all, NULL);
+	}
+	return count;
+}
+
 static const struct file_operations ct_file_ops = {
 	.owner   = THIS_MODULE,
 	.open    = ct_open,
 	.read    = seq_read,
+	.write	 = ct_file_write,
 	.llseek  = seq_lseek,
 	.release = seq_release_net,
 };
@@ -366,7 +396,7 @@
 {
 	struct proc_dir_entry *pde;
 
-	pde = proc_net_fops_create(net, "nf_conntrack", 0440, &ct_file_ops);
+	pde = proc_net_fops_create(net, "nf_conntrack", 0660, &ct_file_ops);
 	if (!pde)
 		goto out_nf_conntrack;
 
diff --git a/net/netfilter/regexp/regexp.c b/net/netfilter/regexp/regexp.c
new file mode 100644
index 0000000..9006988
--- /dev/null
+++ b/net/netfilter/regexp/regexp.c
@@ -0,0 +1,1197 @@
+/*
+ * regcomp and regexec -- regsub and regerror are elsewhere
+ * @(#)regexp.c	1.3 of 18 April 87
+ *
+ *	Copyright (c) 1986 by University of Toronto.
+ *	Written by Henry Spencer.  Not derived from licensed software.
+ *
+ *	Permission is granted to anyone to use this software for any
+ *	purpose on any computer system, and to redistribute it freely,
+ *	subject to the following restrictions:
+ *
+ *	1. The author is not responsible for the consequences of use of
+ *		this software, no matter how awful, even if they arise
+ *		from defects in it.
+ *
+ *	2. The origin of this software must not be misrepresented, either
+ *		by explicit claim or by omission.
+ *
+ *	3. Altered versions must be plainly marked as such, and must not
+ *		be misrepresented as being the original software.
+ *
+ * Beware that some of this code is subtly aware of the way operator
+ * precedence is structured in regular expressions.  Serious changes in
+ * regular-expression syntax might require a total rethink.
+ *
+ * This code was modified by Ethan Sommer to work within the kernel
+ * (it now uses kmalloc etc..)
+ *
+ * Modified slightly by Matthew Strait to use more modern C.
+ */
+
+#include "regexp.h"
+#include "regmagic.h"
+
+/* added by ethan and matt.  Lets it work in both kernel and user space.
+(So iptables can use it, for instance.)  Yea, it goes both ways... */
+#if __KERNEL__
+  #define malloc(foo) kmalloc(foo,GFP_ATOMIC)
+#else
+  #define printk(format,args...) printf(format,##args)
+#endif
+
+void regerror(char * s)
+{
+        printk("<3>Regexp: %s\n", s);
+        /* NOTREACHED */
+}
+
+/*
+ * The "internal use only" fields in regexp.h are present to pass info from
+ * compile to execute that permits the execute phase to run lots faster on
+ * simple cases.  They are:
+ *
+ * regstart	char that must begin a match; '\0' if none obvious
+ * reganch	is the match anchored (at beginning-of-line only)?
+ * regmust	string (pointer into program) that match must include, or NULL
+ * regmlen	length of regmust string
+ *
+ * Regstart and reganch permit very fast decisions on suitable starting points
+ * for a match, cutting down the work a lot.  Regmust permits fast rejection
+ * of lines that cannot possibly match.  The regmust tests are costly enough
+ * that regcomp() supplies a regmust only if the r.e. contains something
+ * potentially expensive (at present, the only such thing detected is * or +
+ * at the start of the r.e., which can involve a lot of backup).  Regmlen is
+ * supplied because the test in regexec() needs it and regcomp() is computing
+ * it anyway.
+ */
+
+/*
+ * Structure for regexp "program".  This is essentially a linear encoding
+ * of a nondeterministic finite-state machine (aka syntax charts or
+ * "railroad normal form" in parsing technology).  Each node is an opcode
+ * plus a "next" pointer, possibly plus an operand.  "Next" pointers of
+ * all nodes except BRANCH implement concatenation; a "next" pointer with
+ * a BRANCH on both ends of it is connecting two alternatives.  (Here we
+ * have one of the subtle syntax dependencies:  an individual BRANCH (as
+ * opposed to a collection of them) is never concatenated with anything
+ * because of operator precedence.)  The operand of some types of node is
+ * a literal string; for others, it is a node leading into a sub-FSM.  In
+ * particular, the operand of a BRANCH node is the first node of the branch.
+ * (NB this is *not* a tree structure:  the tail of the branch connects
+ * to the thing following the set of BRANCHes.)  The opcodes are:
+ */
+
+/* definition	number	opnd?	meaning */
+#define	END	0	/* no	End of program. */
+#define	BOL	1	/* no	Match "" at beginning of line. */
+#define	EOL	2	/* no	Match "" at end of line. */
+#define	ANY	3	/* no	Match any one character. */
+#define	ANYOF	4	/* str	Match any character in this string. */
+#define	ANYBUT	5	/* str	Match any character not in this string. */
+#define	BRANCH	6	/* node	Match this alternative, or the next... */
+#define	BACK	7	/* no	Match "", "next" ptr points backward. */
+#define	EXACTLY	8	/* str	Match this string. */
+#define	NOTHING	9	/* no	Match empty string. */
+#define	STAR	10	/* node	Match this (simple) thing 0 or more times. */
+#define	PLUS	11	/* node	Match this (simple) thing 1 or more times. */
+#define	OPEN	20	/* no	Mark this point in input as start of #n. */
+			/*	OPEN+1 is number 1, etc. */
+#define	CLOSE	30	/* no	Analogous to OPEN. */
+
+/*
+ * Opcode notes:
+ *
+ * BRANCH	The set of branches constituting a single choice are hooked
+ *		together with their "next" pointers, since precedence prevents
+ *		anything being concatenated to any individual branch.  The
+ *		"next" pointer of the last BRANCH in a choice points to the
+ *		thing following the whole choice.  This is also where the
+ *		final "next" pointer of each individual branch points; each
+ *		branch starts with the operand node of a BRANCH node.
+ *
+ * BACK		Normal "next" pointers all implicitly point forward; BACK
+ *		exists to make loop structures possible.
+ *
+ * STAR,PLUS	'?', and complex '*' and '+', are implemented as circular
+ *		BRANCH structures using BACK.  Simple cases (one character
+ *		per match) are implemented with STAR and PLUS for speed
+ *		and to minimize recursive plunges.
+ *
+ * OPEN,CLOSE	...are numbered at compile time.
+ */
+
+/*
+ * A node is one char of opcode followed by two chars of "next" pointer.
+ * "Next" pointers are stored as two 8-bit pieces, high order first.  The
+ * value is a positive offset from the opcode of the node containing it.
+ * An operand, if any, simply follows the node.  (Note that much of the
+ * code generation knows about this implicit relationship.)
+ *
+ * Using two bytes for the "next" pointer is vast overkill for most things,
+ * but allows patterns to get big without disasters.
+ */
+#define	OP(p)	(*(p))
+#define	NEXT(p)	(((*((p)+1)&0377)<<8) + (*((p)+2)&0377))
+#define	OPERAND(p)	((p) + 3)
+
+/*
+ * See regmagic.h for one further detail of program structure.
+ */
+
+
+/*
+ * Utility definitions.
+ */
+#ifndef CHARBITS
+#define	UCHARAT(p)	((int)*(unsigned char *)(p))
+#else
+#define	UCHARAT(p)	((int)*(p)&CHARBITS)
+#endif
+
+#define	FAIL(m)	{ regerror(m); return(NULL); }
+#define	ISMULT(c)	((c) == '*' || (c) == '+' || (c) == '?')
+#define	META	"^$.[()|?+*\\"
+
+/*
+ * Flags to be passed up and down.
+ */
+#define	HASWIDTH	01	/* Known never to match null string. */
+#define	SIMPLE		02	/* Simple enough to be STAR/PLUS operand. */
+#define	SPSTART		04	/* Starts with * or +. */
+#define	WORST		0	/* Worst case. */
+
+/*
+ * Global work variables for regcomp().
+ */
+struct match_globals {
+char *reginput;		/* String-input pointer. */
+char *regbol;		/* Beginning of input, for ^ check. */
+char **regstartp;	/* Pointer to startp array. */
+char **regendp;		/* Ditto for endp. */
+char *regparse;		/* Input-scan pointer. */
+int regnpar;		/* () count. */
+char regdummy;
+char *regcode;		/* Code-emit pointer; &regdummy = don't. */
+long regsize;		/* Code size. */
+};
+
+/*
+ * Forward declarations for regcomp()'s friends.
+ */
+#ifndef STATIC
+#define	STATIC	static
+#endif
+STATIC char *reg(struct match_globals *g, int paren,int *flagp);
+STATIC char *regbranch(struct match_globals *g, int *flagp);
+STATIC char *regpiece(struct match_globals *g, int *flagp);
+STATIC char *regatom(struct match_globals *g, int *flagp);
+STATIC char *regnode(struct match_globals *g, char op);
+STATIC char *regnext(struct match_globals *g, char *p);
+STATIC void regc(struct match_globals *g, char b);
+STATIC void reginsert(struct match_globals *g, char op, char *opnd);
+STATIC void regtail(struct match_globals *g, char *p, char *val);
+STATIC void regoptail(struct match_globals *g, char *p, char *val);
+
+
+__kernel_size_t my_strcspn(const char *s1,const char *s2)
+{
+        char *scan1;
+        char *scan2;
+        int count;
+
+        count = 0;
+        for (scan1 = (char *)s1; *scan1 != '\0'; scan1++) {
+                for (scan2 = (char *)s2; *scan2 != '\0';)       /* ++ moved down. */
+                        if (*scan1 == *scan2++)
+                                return(count);
+                count++;
+        }
+        return(count);
+}
+
+/*
+ - regcomp - compile a regular expression into internal code
+ *
+ * We can't allocate space until we know how big the compiled form will be,
+ * but we can't compile it (and thus know how big it is) until we've got a
+ * place to put the code.  So we cheat:  we compile it twice, once with code
+ * generation turned off and size counting turned on, and once "for real".
+ * This also means that we don't allocate space until we are sure that the
+ * thing really will compile successfully, and we never have to move the
+ * code and thus invalidate pointers into it.  (Note that it has to be in
+ * one piece because free() must be able to free it all.)
+ *
+ * Beware that the optimization-preparation code in here knows about some
+ * of the structure of the compiled regexp.
+ */
+regexp *
+regcomp(char *exp,int *patternsize)
+{
+	register regexp *r;
+	register char *scan;
+	register char *longest;
+	register int len;
+	int flags;
+	struct match_globals g;
+	
+	/* commented out by ethan
+	   extern char *malloc();
+	*/
+
+	if (exp == NULL)
+		FAIL("NULL argument");
+
+	/* First pass: determine size, legality. */
+	g.regparse = exp;
+	g.regnpar = 1;
+	g.regsize = 0L;
+	g.regcode = &g.regdummy;
+	regc(&g, MAGIC);
+	if (reg(&g, 0, &flags) == NULL)
+		return(NULL);
+
+	/* Small enough for pointer-storage convention? */
+	if (g.regsize >= 32767L)		/* Probably could be 65535L. */
+		FAIL("regexp too big");
+
+	/* Allocate space. */
+	*patternsize=sizeof(regexp) + (unsigned)g.regsize;
+	r = (regexp *)malloc(sizeof(regexp) + (unsigned)g.regsize);
+	if (r == NULL)
+		FAIL("out of space");
+
+	/* Second pass: emit code. */
+	g.regparse = exp;
+	g.regnpar = 1;
+	g.regcode = r->program;
+	regc(&g, MAGIC);
+	if (reg(&g, 0, &flags) == NULL)
+		return(NULL);
+
+	/* Dig out information for optimizations. */
+	r->regstart = '\0';	/* Worst-case defaults. */
+	r->reganch = 0;
+	r->regmust = NULL;
+	r->regmlen = 0;
+	scan = r->program+1;			/* First BRANCH. */
+	if (OP(regnext(&g, scan)) == END) {		/* Only one top-level choice. */
+		scan = OPERAND(scan);
+
+		/* Starting-point info. */
+		if (OP(scan) == EXACTLY)
+			r->regstart = *OPERAND(scan);
+		else if (OP(scan) == BOL)
+			r->reganch++;
+
+		/*
+		 * If there's something expensive in the r.e., find the
+		 * longest literal string that must appear and make it the
+		 * regmust.  Resolve ties in favor of later strings, since
+		 * the regstart check works with the beginning of the r.e.
+		 * and avoiding duplication strengthens checking.  Not a
+		 * strong reason, but sufficient in the absence of others.
+		 */
+		if (flags&SPSTART) {
+			longest = NULL;
+			len = 0;
+			for (; scan != NULL; scan = regnext(&g, scan))
+				if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) {
+					longest = OPERAND(scan);
+					len = strlen(OPERAND(scan));
+				}
+			r->regmust = longest;
+			r->regmlen = len;
+		}
+	}
+
+	return(r);
+}
+
+/*
+ - reg - regular expression, i.e. main body or parenthesized thing
+ *
+ * Caller must absorb opening parenthesis.
+ *
+ * Combining parenthesis handling with the base level of regular expression
+ * is a trifle forced, but the need to tie the tails of the branches to what
+ * follows makes it hard to avoid.
+ */
+static char *
+reg(struct match_globals *g, int paren, int *flagp /* Parenthesized? */ )
+{
+	register char *ret;
+	register char *br;
+	register char *ender;
+	register int parno = 0; /* 0 makes gcc happy */
+	int flags;
+
+	*flagp = HASWIDTH;	/* Tentatively. */
+
+	/* Make an OPEN node, if parenthesized. */
+	if (paren) {
+		if (g->regnpar >= NSUBEXP)
+			FAIL("too many ()");
+		parno = g->regnpar;
+		g->regnpar++;
+		ret = regnode(g, OPEN+parno);
+	} else
+		ret = NULL;
+
+	/* Pick up the branches, linking them together. */
+	br = regbranch(g, &flags);
+	if (br == NULL)
+		return(NULL);
+	if (ret != NULL)
+		regtail(g, ret, br);	/* OPEN -> first. */
+	else
+		ret = br;
+	if (!(flags&HASWIDTH))
+		*flagp &= ~HASWIDTH;
+	*flagp |= flags&SPSTART;
+	while (*g->regparse == '|') {
+		g->regparse++;
+		br = regbranch(g, &flags);
+		if (br == NULL)
+			return(NULL);
+		regtail(g, ret, br);	/* BRANCH -> BRANCH. */
+		if (!(flags&HASWIDTH))
+			*flagp &= ~HASWIDTH;
+		*flagp |= flags&SPSTART;
+	}
+
+	/* Make a closing node, and hook it on the end. */
+	ender = regnode(g, (paren) ? CLOSE+parno : END);	
+	regtail(g, ret, ender);
+
+	/* Hook the tails of the branches to the closing node. */
+	for (br = ret; br != NULL; br = regnext(g, br))
+		regoptail(g, br, ender);
+
+	/* Check for proper termination. */
+	if (paren && *g->regparse++ != ')') {
+		FAIL("unmatched ()");
+	} else if (!paren && *g->regparse != '\0') {
+		if (*g->regparse == ')') {
+			FAIL("unmatched ()");
+		} else
+			FAIL("junk on end");	/* "Can't happen". */
+		/* NOTREACHED */
+	}
+
+	return(ret);
+}
+
+/*
+ - regbranch - one alternative of an | operator
+ *
+ * Implements the concatenation operator.
+ */
+static char *
+regbranch(struct match_globals *g, int *flagp)
+{
+	register char *ret;
+	register char *chain;
+	register char *latest;
+	int flags;
+
+	*flagp = WORST;		/* Tentatively. */
+
+	ret = regnode(g, BRANCH);
+	chain = NULL;
+	while (*g->regparse != '\0' && *g->regparse != '|' && *g->regparse != ')') {
+		latest = regpiece(g, &flags);
+		if (latest == NULL)
+			return(NULL);
+		*flagp |= flags&HASWIDTH;
+		if (chain == NULL)	/* First piece. */
+			*flagp |= flags&SPSTART;
+		else
+			regtail(g, chain, latest);
+		chain = latest;
+	}
+	if (chain == NULL)	/* Loop ran zero times. */
+		(void) regnode(g, NOTHING);
+
+	return(ret);
+}
+
+/*
+ - regpiece - something followed by possible [*+?]
+ *
+ * Note that the branching code sequences used for ? and the general cases
+ * of * and + are somewhat optimized:  they use the same NOTHING node as
+ * both the endmarker for their branch list and the body of the last branch.
+ * It might seem that this node could be dispensed with entirely, but the
+ * endmarker role is not redundant.
+ */
+static char *
+regpiece(struct match_globals *g, int *flagp)
+{
+	register char *ret;
+	register char op;
+	register char *next;
+	int flags;
+
+	ret = regatom(g, &flags);
+	if (ret == NULL)
+		return(NULL);
+
+	op = *g->regparse;
+	if (!ISMULT(op)) {
+		*flagp = flags;
+		return(ret);
+	}
+
+	if (!(flags&HASWIDTH) && op != '?')
+		FAIL("*+ operand could be empty");
+	*flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH);
+
+	if (op == '*' && (flags&SIMPLE))
+		reginsert(g, STAR, ret);
+	else if (op == '*') {
+		/* Emit x* as (x&|), where & means "self". */
+		reginsert(g, BRANCH, ret);			/* Either x */
+		regoptail(g, ret, regnode(g, BACK));		/* and loop */
+		regoptail(g, ret, ret);			/* back */
+		regtail(g, ret, regnode(g, BRANCH));		/* or */
+		regtail(g, ret, regnode(g, NOTHING));		/* null. */
+	} else if (op == '+' && (flags&SIMPLE))
+		reginsert(g, PLUS, ret);
+	else if (op == '+') {
+		/* Emit x+ as x(&|), where & means "self". */
+		next = regnode(g, BRANCH);			/* Either */
+		regtail(g, ret, next);
+		regtail(g, regnode(g, BACK), ret);		/* loop back */
+		regtail(g, next, regnode(g, BRANCH));		/* or */
+		regtail(g, ret, regnode(g, NOTHING));		/* null. */
+	} else if (op == '?') {
+		/* Emit x? as (x|) */
+		reginsert(g, BRANCH, ret);			/* Either x */
+		regtail(g, ret, regnode(g, BRANCH));		/* or */
+		next = regnode(g, NOTHING);		/* null. */
+		regtail(g, ret, next);
+		regoptail(g, ret, next);
+	}
+	g->regparse++;
+	if (ISMULT(*g->regparse))
+		FAIL("nested *?+");
+
+	return(ret);
+}
+
+/*
+ - regatom - the lowest level
+ *
+ * Optimization:  gobbles an entire sequence of ordinary characters so that
+ * it can turn them into a single node, which is smaller to store and
+ * faster to run.  Backslashed characters are exceptions, each becoming a
+ * separate node; the code is simpler that way and it's not worth fixing.
+ */
+static char *
+regatom(struct match_globals *g, int *flagp)
+{
+	register char *ret;
+	int flags;
+
+	*flagp = WORST;		/* Tentatively. */
+
+	switch (*g->regparse++) {
+	case '^':
+		ret = regnode(g, BOL);
+		break;
+	case '$':
+		ret = regnode(g, EOL);
+		break;
+	case '.':
+		ret = regnode(g, ANY);
+		*flagp |= HASWIDTH|SIMPLE;
+		break;
+	case '[': {
+			register int class;
+			register int classend;
+
+			if (*g->regparse == '^') {	/* Complement of range. */
+				ret = regnode(g, ANYBUT);
+				g->regparse++;
+			} else
+				ret = regnode(g, ANYOF);
+			if (*g->regparse == ']' || *g->regparse == '-')
+				regc(g, *g->regparse++);
+			while (*g->regparse != '\0' && *g->regparse != ']') {
+				if (*g->regparse == '-') {
+					g->regparse++;
+					if (*g->regparse == ']' || *g->regparse == '\0')
+						regc(g, '-');
+					else {
+						class = UCHARAT(g->regparse-2)+1;
+						classend = UCHARAT(g->regparse);
+						if (class > classend+1)
+							FAIL("invalid [] range");
+						for (; class <= classend; class++)
+							regc(g, class);
+						g->regparse++;
+					}
+				} else
+					regc(g, *g->regparse++);
+			}
+			regc(g, '\0');
+			if (*g->regparse != ']')
+				FAIL("unmatched []");
+			g->regparse++;
+			*flagp |= HASWIDTH|SIMPLE;
+		}
+		break;
+	case '(':
+		ret = reg(g, 1, &flags);
+		if (ret == NULL)
+			return(NULL);
+		*flagp |= flags&(HASWIDTH|SPSTART);
+		break;
+	case '\0':
+	case '|':
+	case ')':
+		FAIL("internal urp");	/* Supposed to be caught earlier. */
+		break;
+	case '?':
+	case '+':
+	case '*':
+		FAIL("?+* follows nothing");
+		break;
+	case '\\':
+		if (*g->regparse == '\0')
+			FAIL("trailing \\");
+		ret = regnode(g, EXACTLY);
+		regc(g, *g->regparse++);
+		regc(g, '\0');
+		*flagp |= HASWIDTH|SIMPLE;
+		break;
+	default: {
+			register int len;
+			register char ender;
+
+			g->regparse--;
+			len = my_strcspn((const char *)g->regparse, (const char *)META);
+			if (len <= 0)
+				FAIL("internal disaster");
+			ender = *(g->regparse+len);
+			if (len > 1 && ISMULT(ender))
+				len--;		/* Back off clear of ?+* operand. */
+			*flagp |= HASWIDTH;
+			if (len == 1)
+				*flagp |= SIMPLE;
+			ret = regnode(g, EXACTLY);
+			while (len > 0) {
+				regc(g, *g->regparse++);
+				len--;
+			}
+			regc(g, '\0');
+		}
+		break;
+	}
+
+	return(ret);
+}
+
+/*
+ - regnode - emit a node
+ */
+static char *			/* Location. */
+regnode(struct match_globals *g, char op)
+{
+	register char *ret;
+	register char *ptr;
+
+	ret = g->regcode;
+	if (ret == &g->regdummy) {
+		g->regsize += 3;
+		return(ret);
+	}
+
+	ptr = ret;
+	*ptr++ = op;
+	*ptr++ = '\0';		/* Null "next" pointer. */
+	*ptr++ = '\0';
+	g->regcode = ptr;
+
+	return(ret);
+}
+
+/*
+ - regc - emit (if appropriate) a byte of code
+ */
+static void
+regc(struct match_globals *g, char b)
+{
+	if (g->regcode != &g->regdummy)
+		*g->regcode++ = b;
+	else
+		g->regsize++;
+}
+
+/*
+ - reginsert - insert an operator in front of already-emitted operand
+ *
+ * Means relocating the operand.
+ */
+static void
+reginsert(struct match_globals *g, char op, char* opnd)
+{
+	register char *src;
+	register char *dst;
+	register char *place;
+
+	if (g->regcode == &g->regdummy) {
+		g->regsize += 3;
+		return;
+	}
+
+	src = g->regcode;
+	g->regcode += 3;
+	dst = g->regcode;
+	while (src > opnd)
+		*--dst = *--src;
+
+	place = opnd;		/* Op node, where operand used to be. */
+	*place++ = op;
+	*place++ = '\0';
+	*place++ = '\0';
+}
+
+/*
+ - regtail - set the next-pointer at the end of a node chain
+ */
+static void
+regtail(struct match_globals *g, char *p, char *val)
+{
+	register char *scan;
+	register char *temp;
+	register int offset;
+
+	if (p == &g->regdummy)
+		return;
+
+	/* Find last node. */
+	scan = p;
+	for (;;) {
+		temp = regnext(g, scan);
+		if (temp == NULL)
+			break;
+		scan = temp;
+	}
+
+	if (OP(scan) == BACK)
+		offset = scan - val;
+	else
+		offset = val - scan;
+	*(scan+1) = (offset>>8)&0377;
+	*(scan+2) = offset&0377;
+}
+
+/*
+ - regoptail - regtail on operand of first argument; nop if operandless
+ */
+static void
+regoptail(struct match_globals *g, char *p, char *val)
+{
+	/* "Operandless" and "op != BRANCH" are synonymous in practice. */
+	if (p == NULL || p == &g->regdummy || OP(p) != BRANCH)
+		return;
+	regtail(g, OPERAND(p), val);
+}
+
+/*
+ * regexec and friends
+ */
+
+
+/*
+ * Forwards.
+ */
+STATIC int regtry(struct match_globals *g, regexp *prog, char *string);
+STATIC int regmatch(struct match_globals *g, char *prog);
+STATIC int regrepeat(struct match_globals *g, char *p);
+
+#ifdef DEBUG
+int regnarrate = 0;
+void regdump();
+STATIC char *regprop(char *op);
+#endif
+
+/*
+ - regexec - match a regexp against a string
+ */
+int
+regexec(regexp *prog, char *string)
+{
+	register char *s;
+	struct match_globals g;
+
+	/* Be paranoid... */
+	if (prog == NULL || string == NULL) {
+		printk("<3>Regexp: NULL parameter\n");
+		return(0);
+	}
+
+	/* Check validity of program. */
+	if (UCHARAT(prog->program) != MAGIC) {
+		printk("<3>Regexp: corrupted program\n");
+		return(0);
+	}
+
+	/* If there is a "must appear" string, look for it. */
+	if (prog->regmust != NULL) {
+		s = string;
+		while ((s = strchr(s, prog->regmust[0])) != NULL) {
+			if (strncmp(s, prog->regmust, prog->regmlen) == 0)
+				break;	/* Found it. */
+			s++;
+		}
+		if (s == NULL)	/* Not present. */
+			return(0);
+	}
+
+	/* Mark beginning of line for ^ . */
+	g.regbol = string;
+
+	/* Simplest case:  anchored match need be tried only once. */
+	if (prog->reganch)
+		return(regtry(&g, prog, string));
+
+	/* Messy cases:  unanchored match. */
+	s = string;
+	if (prog->regstart != '\0')
+		/* We know what char it must start with. */
+		while ((s = strchr(s, prog->regstart)) != NULL) {
+			if (regtry(&g, prog, s))
+				return(1);
+			s++;
+		}
+	else
+		/* We don't -- general case. */
+		do {
+			if (regtry(&g, prog, s))
+				return(1);
+		} while (*s++ != '\0');
+
+	/* Failure. */
+	return(0);
+}
+
+/*
+ - regtry - try match at specific point
+ */
+static int			/* 0 failure, 1 success */
+regtry(struct match_globals *g, regexp *prog, char *string)
+{
+	register int i;
+	register char **sp;
+	register char **ep;
+
+	g->reginput = string;
+	g->regstartp = prog->startp;
+	g->regendp = prog->endp;
+
+	sp = prog->startp;
+	ep = prog->endp;
+	for (i = NSUBEXP; i > 0; i--) {
+		*sp++ = NULL;
+		*ep++ = NULL;
+	}
+	if (regmatch(g, prog->program + 1)) {
+		prog->startp[0] = string;
+		prog->endp[0] = g->reginput;
+		return(1);
+	} else
+		return(0);
+}
+
+/*
+ - regmatch - main matching routine
+ *
+ * Conceptually the strategy is simple:  check to see whether the current
+ * node matches, call self recursively to see whether the rest matches,
+ * and then act accordingly.  In practice we make some effort to avoid
+ * recursion, in particular by going through "ordinary" nodes (that don't
+ * need to know whether the rest of the match failed) by a loop instead of
+ * by recursion.
+ */
+static int			/* 0 failure, 1 success */
+regmatch(struct match_globals *g, char *prog)
+{
+	register char *scan = prog; /* Current node. */
+	char *next;		    /* Next node. */
+
+#ifdef DEBUG
+	if (scan != NULL && regnarrate)
+		fprintf(stderr, "%s(\n", regprop(scan));
+#endif
+	while (scan != NULL) {
+#ifdef DEBUG
+		if (regnarrate)
+			fprintf(stderr, "%s...\n", regprop(scan));
+#endif
+		next = regnext(g, scan);
+
+		switch (OP(scan)) {
+		case BOL:
+			if (g->reginput != g->regbol)
+				return(0);
+			break;
+		case EOL:
+			if (*g->reginput != '\0')
+				return(0);
+			break;
+		case ANY:
+			if (*g->reginput == '\0')
+				return(0);
+			g->reginput++;
+			break;
+		case EXACTLY: {
+				register int len;
+				register char *opnd;
+
+				opnd = OPERAND(scan);
+				/* Inline the first character, for speed. */
+				if (*opnd != *g->reginput)
+					return(0);
+				len = strlen(opnd);
+				if (len > 1 && strncmp(opnd, g->reginput, len) != 0)
+					return(0);
+				g->reginput += len;
+			}
+			break;
+		case ANYOF:
+			if (*g->reginput == '\0' || strchr(OPERAND(scan), *g->reginput) == NULL)
+				return(0);
+			g->reginput++;
+			break;
+		case ANYBUT:
+			if (*g->reginput == '\0' || strchr(OPERAND(scan), *g->reginput) != NULL)
+				return(0);
+			g->reginput++;
+			break;
+		case NOTHING:
+		case BACK:
+			break;
+		case OPEN+1:
+		case OPEN+2:
+		case OPEN+3:
+		case OPEN+4:
+		case OPEN+5:
+		case OPEN+6:
+		case OPEN+7:
+		case OPEN+8:
+		case OPEN+9: {
+				register int no;
+				register char *save;
+
+				no = OP(scan) - OPEN;
+				save = g->reginput;
+
+				if (regmatch(g, next)) {
+					/*
+					 * Don't set startp if some later
+					 * invocation of the same parentheses
+					 * already has.
+					 */
+					if (g->regstartp[no] == NULL)
+						g->regstartp[no] = save;
+					return(1);
+				} else
+					return(0);
+			}
+			break;
+		case CLOSE+1:
+		case CLOSE+2:
+		case CLOSE+3:
+		case CLOSE+4:
+		case CLOSE+5:
+		case CLOSE+6:
+		case CLOSE+7:
+		case CLOSE+8:
+		case CLOSE+9:
+			{
+				register int no;
+				register char *save;
+
+				no = OP(scan) - CLOSE;
+				save = g->reginput;
+
+				if (regmatch(g, next)) {
+					/*
+					 * Don't set endp if some later
+					 * invocation of the same parentheses
+					 * already has.
+					 */
+					if (g->regendp[no] == NULL)
+						g->regendp[no] = save;
+					return(1);
+				} else
+					return(0);
+			}
+			break;
+		case BRANCH: {
+				register char *save;
+
+				if (OP(next) != BRANCH)		/* No choice. */
+					next = OPERAND(scan);	/* Avoid recursion. */
+				else {
+					do {
+						save = g->reginput;
+						if (regmatch(g, OPERAND(scan)))
+							return(1);
+						g->reginput = save;
+						scan = regnext(g, scan);
+					} while (scan != NULL && OP(scan) == BRANCH);
+					return(0);
+					/* NOTREACHED */
+				}
+			}
+			break;
+		case STAR:
+		case PLUS: {
+				register char nextch;
+				register int no;
+				register char *save;
+				register int min;
+
+				/*
+				 * Lookahead to avoid useless match attempts
+				 * when we know what character comes next.
+				 */
+				nextch = '\0';
+				if (OP(next) == EXACTLY)
+					nextch = *OPERAND(next);
+				min = (OP(scan) == STAR) ? 0 : 1;
+				save = g->reginput;
+				no = regrepeat(g, OPERAND(scan));
+				while (no >= min) {
+					/* If it could work, try it. */
+					if (nextch == '\0' || *g->reginput == nextch)
+						if (regmatch(g, next))
+							return(1);
+					/* Couldn't or didn't -- back up. */
+					no--;
+					g->reginput = save + no;
+				}
+				return(0);
+			}
+			break;
+		case END:
+			return(1);	/* Success! */
+			break;
+		default:
+			printk("<3>Regexp: memory corruption\n");
+			return(0);
+			break;
+		}
+
+		scan = next;
+	}
+
+	/*
+	 * We get here only if there's trouble -- normally "case END" is
+	 * the terminating point.
+	 */
+	printk("<3>Regexp: corrupted pointers\n");
+	return(0);
+}
+
+/*
+ - regrepeat - repeatedly match something simple, report how many
+ */
+static int
+regrepeat(struct match_globals *g, char *p)
+{
+	register int count = 0;
+	register char *scan;
+	register char *opnd;
+
+	scan = g->reginput;
+	opnd = OPERAND(p);
+	switch (OP(p)) {
+	case ANY:
+		count = strlen(scan);
+		scan += count;
+		break;
+	case EXACTLY:
+		while (*opnd == *scan) {
+			count++;
+			scan++;
+		}
+		break;
+	case ANYOF:
+		while (*scan != '\0' && strchr(opnd, *scan) != NULL) {
+			count++;
+			scan++;
+		}
+		break;
+	case ANYBUT:
+		while (*scan != '\0' && strchr(opnd, *scan) == NULL) {
+			count++;
+			scan++;
+		}
+		break;
+	default:		/* Oh dear.  Called inappropriately. */
+		printk("<3>Regexp: internal foulup\n");
+		count = 0;	/* Best compromise. */
+		break;
+	}
+	g->reginput = scan;
+
+	return(count);
+}
+
+/*
+ - regnext - dig the "next" pointer out of a node
+ */
+static char*
+regnext(struct match_globals *g, char *p)
+{
+	register int offset;
+
+	if (p == &g->regdummy)
+		return(NULL);
+
+	offset = NEXT(p);
+	if (offset == 0)
+		return(NULL);
+
+	if (OP(p) == BACK)
+		return(p-offset);
+	else
+		return(p+offset);
+}
+
+#ifdef DEBUG
+
+STATIC char *regprop();
+
+/*
+ - regdump - dump a regexp onto stdout in vaguely comprehensible form
+ */
+void
+regdump(regexp *r)
+{
+	register char *s;
+	register char op = EXACTLY;	/* Arbitrary non-END op. */
+	register char *next;
+	/* extern char *strchr(); */
+
+
+	s = r->program + 1;
+	while (op != END) {	/* While that wasn't END last time... */
+		op = OP(s);
+		printf("%2d%s", s-r->program, regprop(s));	/* Where, what. */
+		next = regnext(s);
+		if (next == NULL)		/* Next ptr. */
+			printf("(0)");
+		else
+			printf("(%d)", (s-r->program)+(next-s));
+		s += 3;
+		if (op == ANYOF || op == ANYBUT || op == EXACTLY) {
+			/* Literal string, where present. */
+			while (*s != '\0') {
+				putchar(*s);
+				s++;
+			}
+			s++;
+		}
+		putchar('\n');
+	}
+
+	/* Header fields of interest. */
+	if (r->regstart != '\0')
+		printf("start `%c' ", r->regstart);
+	if (r->reganch)
+		printf("anchored ");
+	if (r->regmust != NULL)
+		printf("must have \"%s\"", r->regmust);
+	printf("\n");
+}
+
+/*
+ - regprop - printable representation of opcode
+ */
+static char *
+regprop(char *op)
+{
+#define BUFLEN 50
+	register char *p;
+	static char buf[BUFLEN];
+
+	strcpy(buf, ":");
+
+	switch (OP(op)) {
+	case BOL:
+		p = "BOL";
+		break;
+	case EOL:
+		p = "EOL";
+		break;
+	case ANY:
+		p = "ANY";
+		break;
+	case ANYOF:
+		p = "ANYOF";
+		break;
+	case ANYBUT:
+		p = "ANYBUT";
+		break;
+	case BRANCH:
+		p = "BRANCH";
+		break;
+	case EXACTLY:
+		p = "EXACTLY";
+		break;
+	case NOTHING:
+		p = "NOTHING";
+		break;
+	case BACK:
+		p = "BACK";
+		break;
+	case END:
+		p = "END";
+		break;
+	case OPEN+1:
+	case OPEN+2:
+	case OPEN+3:
+	case OPEN+4:
+	case OPEN+5:
+	case OPEN+6:
+	case OPEN+7:
+	case OPEN+8:
+	case OPEN+9:
+		snprintf(buf+strlen(buf),BUFLEN-strlen(buf), "OPEN%d", OP(op)-OPEN);
+		p = NULL;
+		break;
+	case CLOSE+1:
+	case CLOSE+2:
+	case CLOSE+3:
+	case CLOSE+4:
+	case CLOSE+5:
+	case CLOSE+6:
+	case CLOSE+7:
+	case CLOSE+8:
+	case CLOSE+9:
+		snprintf(buf+strlen(buf),BUFLEN-strlen(buf), "CLOSE%d", OP(op)-CLOSE);
+		p = NULL;
+		break;
+	case STAR:
+		p = "STAR";
+		break;
+	case PLUS:
+		p = "PLUS";
+		break;
+	default:
+		printk("<3>Regexp: corrupted opcode\n");
+		break;
+	}
+	if (p != NULL)
+		strncat(buf, p, BUFLEN-strlen(buf));
+	return(buf);
+}
+#endif
+
+
diff --git a/net/netfilter/regexp/regexp.h b/net/netfilter/regexp/regexp.h
new file mode 100644
index 0000000..a72eba7
--- /dev/null
+++ b/net/netfilter/regexp/regexp.h
@@ -0,0 +1,41 @@
+/*
+ * Definitions etc. for regexp(3) routines.
+ *
+ * Caveat:  this is V8 regexp(3) [actually, a reimplementation thereof],
+ * not the System V one.
+ */
+
+#ifndef REGEXP_H
+#define REGEXP_H
+
+
+/*
+http://www.opensource.apple.com/darwinsource/10.3/expect-1/expect/expect.h ,
+which contains a version of this library, says:
+
+ *
+ * NSUBEXP must be at least 10, and no greater than 117 or the parser
+ * will not work properly.
+ *
+
+However, it looks rather like this library is limited to 10.  If you think
+otherwise, let us know.
+*/
+
+#define NSUBEXP  10
+typedef struct regexp {
+	char *startp[NSUBEXP];
+	char *endp[NSUBEXP];
+	char regstart;		/* Internal use only. */
+	char reganch;		/* Internal use only. */
+	char *regmust;		/* Internal use only. */
+	int regmlen;		/* Internal use only. */
+	char program[1];	/* Unwarranted chumminess with compiler. */
+} regexp;
+
+regexp * regcomp(char *exp, int *patternsize);
+int regexec(regexp *prog, char *string);
+void regsub(regexp *prog, char *source, char *dest);
+void regerror(char *s);
+
+#endif
diff --git a/net/netfilter/regexp/regmagic.h b/net/netfilter/regexp/regmagic.h
new file mode 100644
index 0000000..5acf447
--- /dev/null
+++ b/net/netfilter/regexp/regmagic.h
@@ -0,0 +1,5 @@
+/*
+ * The first byte of the regexp internal "program" is actually this magic
+ * number; the start node begins in the second byte.
+ */
+#define	MAGIC	0234
diff --git a/net/netfilter/regexp/regsub.c b/net/netfilter/regexp/regsub.c
new file mode 100644
index 0000000..339631f
--- /dev/null
+++ b/net/netfilter/regexp/regsub.c
@@ -0,0 +1,95 @@
+/*
+ * regsub
+ * @(#)regsub.c	1.3 of 2 April 86
+ *
+ *	Copyright (c) 1986 by University of Toronto.
+ *	Written by Henry Spencer.  Not derived from licensed software.
+ *
+ *	Permission is granted to anyone to use this software for any
+ *	purpose on any computer system, and to redistribute it freely,
+ *	subject to the following restrictions:
+ *
+ *	1. The author is not responsible for the consequences of use of
+ *		this software, no matter how awful, even if they arise
+ *		from defects in it.
+ *
+ *	2. The origin of this software must not be misrepresented, either
+ *		by explicit claim or by omission.
+ *
+ *	3. Altered versions must be plainly marked as such, and must not
+ *		be misrepresented as being the original software.
+ *
+ *
+ * This code was modified by Ethan Sommer to work within the kernel
+ * (it now uses kmalloc etc..)
+ *
+ */
+#include "regexp.h"
+#include "regmagic.h"
+#include <linux/string.h>
+
+
+#ifndef CHARBITS
+#define	UCHARAT(p)	((int)*(unsigned char *)(p))
+#else
+#define	UCHARAT(p)	((int)*(p)&CHARBITS)
+#endif
+
+#if 0
+//void regerror(char * s)
+//{
+//        printk("regexp(3): %s", s);
+//        /* NOTREACHED */
+//}
+#endif
+
+/*
+ - regsub - perform substitutions after a regexp match
+ */
+void
+regsub(regexp * prog, char * source, char * dest)
+{
+	register char *src;
+	register char *dst;
+	register char c;
+	register int no;
+	register int len;
+	
+	/* Not necessary and gcc doesn't like it -MLS */
+	/*extern char *strncpy();*/
+
+	if (prog == NULL || source == NULL || dest == NULL) {
+		regerror("NULL parm to regsub");
+		return;
+	}
+	if (UCHARAT(prog->program) != MAGIC) {
+		regerror("damaged regexp fed to regsub");
+		return;
+	}
+
+	src = source;
+	dst = dest;
+	while ((c = *src++) != '\0') {
+		if (c == '&')
+			no = 0;
+		else if (c == '\\' && '0' <= *src && *src <= '9')
+			no = *src++ - '0';
+		else
+			no = -1;
+
+		if (no < 0) {	/* Ordinary character. */
+			if (c == '\\' && (*src == '\\' || *src == '&'))
+				c = *src++;
+			*dst++ = c;
+		} else if (prog->startp[no] != NULL && prog->endp[no] != NULL) {
+			len = prog->endp[no] - prog->startp[no];
+			(void) strncpy(dst, prog->startp[no], len);
+			dst += len;
+			if (len != 0 && *(dst-1) == '\0') {	/* strncpy hit NUL. */
+				regerror("damaged match string");
+				return;
+			}
+		}
+	}
+	*dst++ = '\0';
+}
diff --git a/net/netfilter/xt_layer7.c b/net/netfilter/xt_layer7.c
new file mode 100644
index 0000000..42b46de
--- /dev/null
+++ b/net/netfilter/xt_layer7.c
@@ -0,0 +1,700 @@
+/*
+  Kernel module to match application layer (OSI layer 7) data in connections.
+
+  http://l7-filter.sf.net
+
+  (C) 2003-2009 Matthew Strait and Ethan Sommer.
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License
+  as published by the Free Software Foundation; either version
+  2 of the License, or (at your option) any later version.
+  http://www.gnu.org/licenses/gpl.txt
+
+  Based on ipt_string.c (C) 2000 Emmanuel Roger <winfield@freegates.be>,
+  xt_helper.c (C) 2002 Harald Welte and cls_layer7.c (C) 2003 Matthew Strait,
+  Ethan Sommer, Justin Levandoski.
+*/
+
+#include <linux/spinlock.h>
+#include <linux/version.h>
+#include <net/ip.h>
+#include <net/tcp.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/netfilter.h>
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_core.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
+#include <net/netfilter/nf_conntrack_extend.h>
+#include <net/netfilter/nf_conntrack_acct.h>
+#endif
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_layer7.h>
+#include <linux/ctype.h>
+#include <linux/proc_fs.h>
+
+#include "regexp/regexp.c"
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Matthew Strait <quadong@users.sf.net>, Ethan Sommer <sommere@users.sf.net>");
+MODULE_DESCRIPTION("iptables application layer match module");
+MODULE_ALIAS("ipt_layer7");
+MODULE_VERSION("2.21");
+
+static int maxdatalen = 2048; // this is the default
+module_param(maxdatalen, int, 0444);
+MODULE_PARM_DESC(maxdatalen, "maximum bytes of data looked at by l7-filter");
+#ifdef CONFIG_NETFILTER_XT_MATCH_LAYER7_DEBUG
+	#define DPRINTK(format,args...) printk(format,##args)
+#else
+	#define DPRINTK(format,args...)
+#endif
+
+/* Number of packets whose data we look at.
+This can be modified through /proc/net/layer7_numpackets */
+static int num_packets = 10;
+
+static struct pattern_cache {
+	char * regex_string;
+	regexp * pattern;
+	struct pattern_cache * next;
+} * first_pattern_cache = NULL;
+
+DEFINE_SPINLOCK(l7_lock);
+
+static int total_acct_packets(struct nf_conn *ct)
+{
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 26)
+	BUG_ON(ct == NULL);
+	return (ct->counters[IP_CT_DIR_ORIGINAL].packets + ct->counters[IP_CT_DIR_REPLY].packets);
+#else
+	struct nf_conn_counter *acct;
+
+	BUG_ON(ct == NULL);
+	acct = nf_conn_acct_find(ct);
+	if (!acct)
+		return 0;
+	return (atomic64_read(&acct[IP_CT_DIR_ORIGINAL].packets) + atomic64_read(&acct[IP_CT_DIR_REPLY].packets));
+#endif
+}
+
+#ifdef CONFIG_IP_NF_MATCH_LAYER7_DEBUG
+/* Converts an unfriendly string into a friendly one by
+replacing unprintables with periods and all whitespace with " ". */
+static char * friendly_print(unsigned char * s)
+{
+	char * f = kmalloc(strlen(s) + 1, GFP_ATOMIC);
+	int i;
+
+	if(!f) {
+		if (net_ratelimit())
+			printk(KERN_ERR "layer7: out of memory in "
+					"friendly_print, bailing.\n");
+		return NULL;
+	}
+
+	for(i = 0; i < strlen(s); i++){
+		if(isprint(s[i]) && s[i] < 128)	f[i] = s[i];
+		else if(isspace(s[i]))		f[i] = ' ';
+		else 				f[i] = '.';
+	}
+	f[i] = '\0';
+	return f;
+}
+
+static char dec2hex(int i)
+{
+	switch (i) {
+		case 0 ... 9:
+			return (i + '0');
+			break;
+		case 10 ... 15:
+			return (i - 10 + 'a');
+			break;
+		default:
+			if (net_ratelimit())
+				printk("layer7: Problem in dec2hex\n");
+			return '\0';
+	}
+}
+
+static char * hex_print(unsigned char * s)
+{
+	char * g = kmalloc(strlen(s)*3 + 1, GFP_ATOMIC);
+	int i;
+
+	if(!g) {
+	       if (net_ratelimit())
+			printk(KERN_ERR "layer7: out of memory in hex_print, "
+					"bailing.\n");
+	       return NULL;
+	}
+
+	for(i = 0; i < strlen(s); i++) {
+		g[i*3    ] = dec2hex(s[i]/16);
+		g[i*3 + 1] = dec2hex(s[i]%16);
+		g[i*3 + 2] = ' ';
+	}
+	g[i*3] = '\0';
+
+	return g;
+}
+#endif // DEBUG
+
+/* Use instead of regcomp.  As we expect to be seeing the same regexps over and
+over again, it make sense to cache the results. */
+static regexp * compile_and_cache(const char * regex_string, 
+                                  const char * protocol)
+{
+	struct pattern_cache * node               = first_pattern_cache;
+	struct pattern_cache * last_pattern_cache = first_pattern_cache;
+	struct pattern_cache * tmp;
+	unsigned int len;
+
+	while (node != NULL) {
+		if (!strcmp(node->regex_string, regex_string))
+		return node->pattern;
+
+		last_pattern_cache = node;/* points at the last non-NULL node */
+		node = node->next;
+	}
+
+	/* If we reach the end of the list, then we have not yet cached
+	   the pattern for this regex. Let's do that now.
+	   Be paranoid about running out of memory to avoid list corruption. */
+	tmp = kmalloc(sizeof(struct pattern_cache), GFP_ATOMIC);
+
+	if(!tmp) {
+		if (net_ratelimit())
+			printk(KERN_ERR "layer7: out of memory in "
+					"compile_and_cache, bailing.\n");
+		return NULL;
+	}
+
+	tmp->regex_string  = kmalloc(strlen(regex_string) + 1, GFP_ATOMIC);
+	tmp->pattern       = kmalloc(sizeof(struct regexp),    GFP_ATOMIC);
+	tmp->next = NULL;
+
+	if(!tmp->regex_string || !tmp->pattern) {
+		if (net_ratelimit())
+			printk(KERN_ERR "layer7: out of memory in "
+					"compile_and_cache, bailing.\n");
+		kfree(tmp->regex_string);
+		kfree(tmp->pattern);
+		kfree(tmp);
+		return NULL;
+	}
+
+	/* Ok.  The new node is all ready now. */
+	node = tmp;
+
+	if(first_pattern_cache == NULL) /* list is empty */
+		first_pattern_cache = node; /* make node the beginning */
+	else
+		last_pattern_cache->next = node; /* attach node to the end */
+
+	/* copy the string and compile the regex */
+	len = strlen(regex_string);
+	DPRINTK("About to compile this: \"%s\"\n", regex_string);
+	node->pattern = regcomp((char *)regex_string, &len);
+	if ( !node->pattern ) {
+		if (net_ratelimit())
+			printk(KERN_ERR "layer7: Error compiling regexp "
+					"\"%s\" (%s)\n", 
+					regex_string, protocol);
+		/* pattern is now cached as NULL, so we won't try again. */
+	}
+
+	strcpy(node->regex_string, regex_string);
+	return node->pattern;
+}
+
+static int can_handle(const struct sk_buff *skb)
+{
+	if(!ip_hdr(skb)) /* not IP */
+		return 0;
+	if(ip_hdr(skb)->protocol != IPPROTO_TCP &&
+	   ip_hdr(skb)->protocol != IPPROTO_UDP &&
+	   ip_hdr(skb)->protocol != IPPROTO_ICMP)
+		return 0;
+	return 1;
+}
+
+/* Returns offset the into the skb->data that the application data starts */
+static int app_data_offset(const struct sk_buff *skb)
+{
+	/* In case we are ported somewhere (ebtables?) where ip_hdr(skb)
+	isn't set, this can be gotten from 4*(skb->data[0] & 0x0f) as well. */
+	int ip_hl = 4*ip_hdr(skb)->ihl;
+
+	if( ip_hdr(skb)->protocol == IPPROTO_TCP ) {
+		/* 12 == offset into TCP header for the header length field.
+		Can't get this with skb->h.th->doff because the tcphdr
+		struct doesn't get set when routing (this is confirmed to be
+		true in Netfilter as well as QoS.) */
+		int tcp_hl = 4*(skb->data[ip_hl + 12] >> 4);
+
+		return ip_hl + tcp_hl;
+	} else if( ip_hdr(skb)->protocol == IPPROTO_UDP  ) {
+		return ip_hl + 8; /* UDP header is always 8 bytes */
+	} else if( ip_hdr(skb)->protocol == IPPROTO_ICMP ) {
+		return ip_hl + 8; /* ICMP header is 8 bytes */
+	} else {
+		if (net_ratelimit())
+			printk(KERN_ERR "layer7: tried to handle unknown "
+					"protocol!\n");
+		return ip_hl + 8; /* something reasonable */
+	}
+}
+
+/* handles whether there's a match when we aren't appending data anymore */
+static int match_no_append(struct nf_conn * conntrack, 
+                           struct nf_conn * master_conntrack, 
+                           enum ip_conntrack_info ctinfo,
+                           enum ip_conntrack_info master_ctinfo,
+                           const struct xt_layer7_info * info)
+{
+	/* If we're in here, throw the app data away */
+	if(master_conntrack->layer7.app_data != NULL) {
+
+	#ifdef CONFIG_IP_NF_MATCH_LAYER7_DEBUG
+		if(!master_conntrack->layer7.app_proto) {
+			char * f = 
+			  friendly_print(master_conntrack->layer7.app_data);
+			char * g = 
+			  hex_print(master_conntrack->layer7.app_data);
+			DPRINTK("\nl7-filter gave up after %d bytes "
+				"(%d packets):\n%s\n",
+				strlen(f), total_acct_packets(master_conntrack), f);
+			kfree(f);
+			DPRINTK("In hex: %s\n", g);
+			kfree(g);
+		}
+	#endif
+
+		kfree(master_conntrack->layer7.app_data);
+		master_conntrack->layer7.app_data = NULL; /* don't free again */
+	}
+
+	if(master_conntrack->layer7.app_proto){
+		/* Here child connections set their .app_proto (for /proc) */
+		if(!conntrack->layer7.app_proto) {
+			conntrack->layer7.app_proto = 
+			  kmalloc(strlen(master_conntrack->layer7.app_proto)+1, 
+			    GFP_ATOMIC);
+			if(!conntrack->layer7.app_proto){
+				if (net_ratelimit())
+					printk(KERN_ERR "layer7: out of memory "
+							"in match_no_append, "
+							"bailing.\n");
+				return 1;
+			}
+			strcpy(conntrack->layer7.app_proto, 
+				master_conntrack->layer7.app_proto);
+		}
+
+		return (!strcmp(master_conntrack->layer7.app_proto, 
+				info->protocol));
+	}
+	else {
+		/* If not classified, set to "unknown" to distinguish from
+		connections that are still being tested. */
+		master_conntrack->layer7.app_proto = 
+			kmalloc(strlen("unknown")+1, GFP_ATOMIC);
+		if(!master_conntrack->layer7.app_proto){
+			if (net_ratelimit())
+				printk(KERN_ERR "layer7: out of memory in "
+						"match_no_append, bailing.\n");
+			return 1;
+		}
+		strcpy(master_conntrack->layer7.app_proto, "unknown");
+		return 0;
+	}
+}
+
+/* add the new app data to the conntrack.  Return number of bytes added. */
+static int add_datastr(char *target, int offset, char *app_data, int len)
+{
+	int length = 0, i;
+	if (!target) return 0;
+
+	/* Strip nulls. Make everything lower case (our regex lib doesn't
+	do case insensitivity).  Add it to the end of the current data. */
+ 	for(i = 0; i < maxdatalen-offset-1 && i < len; i++) {
+		if(app_data[i] != '\0') {
+			/* the kernel version of tolower mungs 'upper ascii' */
+			target[length+offset] =
+				isascii(app_data[i])? 
+					tolower(app_data[i]) : app_data[i];
+			length++;
+		}
+	}
+	target[length+offset] = '\0';
+
+	return length;
+}
+
+/* add the new app data to the conntrack.  Return number of bytes added. */
+static int add_data(struct nf_conn * master_conntrack,
+                    char * app_data, int appdatalen)
+{
+	int length;
+
+	length = add_datastr(master_conntrack->layer7.app_data, master_conntrack->layer7.app_data_len, app_data, appdatalen);
+	master_conntrack->layer7.app_data_len += length;
+
+	return length;
+}
+
+/* taken from drivers/video/modedb.c */
+static int my_atoi(const char *s)
+{
+	int val = 0;
+
+	for (;; s++) {
+		switch (*s) {
+			case '0'...'9':
+			val = 10*val+(*s-'0');
+			break;
+		default:
+			return val;
+		}
+	}
+}
+
+/* write out num_packets to userland. */
+static int layer7_read_proc(char* page, char ** start, off_t off, int count,
+                            int* eof, void * data)
+{
+	if(num_packets > 99 && net_ratelimit())
+		printk(KERN_ERR "layer7: NOT REACHED. num_packets too big\n");
+
+	page[0] = num_packets/10 + '0';
+	page[1] = num_packets%10 + '0';
+	page[2] = '\n';
+	page[3] = '\0';
+
+	*eof=1;
+
+	return 3;
+}
+
+/* Read in num_packets from userland */
+static int layer7_write_proc(struct file* file, const char* buffer,
+                             unsigned long count, void *data)
+{
+	char * foo = kmalloc(count, GFP_ATOMIC);
+
+	if(!foo){
+		if (net_ratelimit())
+			printk(KERN_ERR "layer7: out of memory, bailing. "
+					"num_packets unchanged.\n");
+		return count;
+	}
+
+	if(copy_from_user(foo, buffer, count)) {
+		return -EFAULT;
+	}
+
+
+	num_packets = my_atoi(foo);
+	kfree (foo);
+
+	/* This has an arbitrary limit to make the math easier. I'm lazy.
+	But anyway, 99 is a LOT! If you want more, you're doing it wrong! */
+	if(num_packets > 99) {
+		printk(KERN_WARNING "layer7: num_packets can't be > 99.\n");
+		num_packets = 99;
+	} else if(num_packets < 1) {
+		printk(KERN_WARNING "layer7: num_packets can't be < 1.\n");
+		num_packets = 1;
+	}
+
+	return count;
+}
+
+static bool
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+match(const struct sk_buff *skbin, struct xt_action_param *par)
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
+match(const struct sk_buff *skbin, const struct xt_match_param *par)
+#else
+match(const struct sk_buff *skbin,
+      const struct net_device *in,
+      const struct net_device *out,
+      const struct xt_match *match,
+      const void *matchinfo,
+      int offset,
+      unsigned int protoff,
+      bool *hotdrop)
+#endif
+{
+	/* sidestep const without getting a compiler warning... */
+	struct sk_buff * skb = (struct sk_buff *)skbin; 
+
+	const struct xt_layer7_info * info = 
+	#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
+		par->matchinfo;
+	#else
+		matchinfo;
+	#endif
+
+	enum ip_conntrack_info master_ctinfo, ctinfo;
+	struct nf_conn *master_conntrack, *conntrack;
+	unsigned char *app_data, *tmp_data;
+	unsigned int pattern_result, appdatalen;
+	regexp * comppattern;
+
+	/* Be paranoid/incompetent - lock the entire match function. */
+	spin_lock_bh(&l7_lock);
+
+	if(!can_handle(skb)){
+		DPRINTK("layer7: This is some protocol I can't handle.\n");
+		spin_unlock_bh(&l7_lock);
+		return info->invert;
+	}
+
+	/* Treat parent & all its children together as one connection, except
+	for the purpose of setting conntrack->layer7.app_proto in the actual
+	connection. This makes /proc/net/ip_conntrack more satisfying. */
+	if(!(conntrack = nf_ct_get(skb, &ctinfo)) ||
+	   !(master_conntrack=nf_ct_get(skb,&master_ctinfo))){
+		DPRINTK("layer7: couldn't get conntrack.\n");
+		spin_unlock_bh(&l7_lock);
+		return info->invert;
+	}
+
+	/* Try to get a master conntrack (and its master etc) for FTP, etc. */
+	while (master_ct(master_conntrack) != NULL)
+		master_conntrack = master_ct(master_conntrack);
+
+	/* if we've classified it or seen too many packets */
+	if(!info->pkt && (total_acct_packets(master_conntrack) > num_packets ||
+	   master_conntrack->layer7.app_proto)) {
+
+		pattern_result = match_no_append(conntrack, master_conntrack, 
+						 ctinfo, master_ctinfo, info);
+
+		/* skb->cb[0] == seen. Don't do things twice if there are 
+		multiple l7 rules. I'm not sure that using cb for this purpose 
+		is correct, even though it says "put your private variables 
+		there". But it doesn't look like it is being used for anything
+		else in the skbs that make it here. */
+		skb->cb[0] = 1; /* marking it seen here's probably irrelevant */
+
+		spin_unlock_bh(&l7_lock);
+		return (pattern_result ^ info->invert);
+	}
+
+	if(skb_is_nonlinear(skb)){
+		if(skb_linearize(skb) != 0){
+			if (net_ratelimit())
+				printk(KERN_ERR "layer7: failed to linearize "
+						"packet, bailing.\n");
+			spin_unlock_bh(&l7_lock);
+			return info->invert;
+		}
+	}
+
+	/* now that the skb is linearized, it's safe to set these. */
+	app_data = skb->data + app_data_offset(skb);
+	appdatalen = skb_tail_pointer(skb) - app_data;
+
+	/* the return value gets checked later, when we're ready to use it */
+	comppattern = compile_and_cache(info->pattern, info->protocol);
+
+	if (info->pkt) {
+		tmp_data = kmalloc(maxdatalen, GFP_ATOMIC);
+		if(!tmp_data){
+			if (net_ratelimit())
+				printk(KERN_ERR "layer7: out of memory in match, bailing.\n");
+			return info->invert;
+		}
+
+		tmp_data[0] = '\0';
+		add_datastr(tmp_data, 0, app_data, appdatalen);
+		pattern_result = ((comppattern && regexec(comppattern, tmp_data)) ? 1 : 0);
+
+		kfree(tmp_data);
+		tmp_data = NULL;
+		spin_unlock_bh(&l7_lock);
+
+		return (pattern_result ^ info->invert);
+	}
+
+	/* On the first packet of a connection, allocate space for app data */
+	if(total_acct_packets(master_conntrack) == 1 && !skb->cb[0] && 
+	   !master_conntrack->layer7.app_data){
+		master_conntrack->layer7.app_data = 
+			kmalloc(maxdatalen, GFP_ATOMIC);
+		if(!master_conntrack->layer7.app_data){
+			if (net_ratelimit())
+				printk(KERN_ERR "layer7: out of memory in "
+						"match, bailing.\n");
+			spin_unlock_bh(&l7_lock);
+			return info->invert;
+		}
+
+		master_conntrack->layer7.app_data[0] = '\0';
+	}
+
+	/* Can be here, but unallocated, if numpackets is increased near
+	the beginning of a connection */
+	if(master_conntrack->layer7.app_data == NULL){
+		spin_unlock_bh(&l7_lock);
+		return info->invert; /* unmatched */
+	}
+
+	if(!skb->cb[0]){
+		int newbytes;
+		newbytes = add_data(master_conntrack, app_data, appdatalen);
+
+		if(newbytes == 0) { /* didn't add any data */
+			skb->cb[0] = 1;
+			/* Didn't match before, not going to match now */
+			spin_unlock_bh(&l7_lock);
+			return info->invert;
+		}
+	}
+
+	/* If looking for "unknown", then never match.  "Unknown" means that
+	we've given up; we're still trying with these packets. */
+	if(!strcmp(info->protocol, "unknown")) {
+		pattern_result = 0;
+	/* If looking for "unset", then always match. "Unset" means that we
+	haven't yet classified the connection. */
+	} else if(!strcmp(info->protocol, "unset")) {
+		pattern_result = 2;
+		DPRINTK("layer7: matched unset: not yet classified "
+			"(%d/%d packets)\n",
+                        total_acct_packets(master_conntrack), num_packets);
+	/* If the regexp failed to compile, don't bother running it */
+	} else if(comppattern && 
+		  regexec(comppattern, master_conntrack->layer7.app_data)){
+		DPRINTK("layer7: matched %s\n", info->protocol);
+		pattern_result = 1;
+	} else pattern_result = 0;
+
+	if(pattern_result == 1) {
+		master_conntrack->layer7.app_proto = 
+			kmalloc(strlen(info->protocol)+1, GFP_ATOMIC);
+		if(!master_conntrack->layer7.app_proto){
+			if (net_ratelimit())
+				printk(KERN_ERR "layer7: out of memory in "
+						"match, bailing.\n");
+			spin_unlock_bh(&l7_lock);
+			return (pattern_result ^ info->invert);
+		}
+		strcpy(master_conntrack->layer7.app_proto, info->protocol);
+	} else if(pattern_result > 1) { /* cleanup from "unset" */
+		pattern_result = 1;
+	}
+
+	/* mark the packet seen */
+	skb->cb[0] = 1;
+
+	spin_unlock_bh(&l7_lock);
+	return (pattern_result ^ info->invert);
+}
+
+// load nf_conntrack_ipv4
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+static int
+#else
+static bool
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
+check(const struct xt_mtchk_param *par)
+{
+        if (nf_ct_l3proto_try_module_get(par->match->family) < 0) {
+                printk(KERN_WARNING "can't load conntrack support for "
+                                    "proto=%d\n", par->match->family);
+#else
+check(const char *tablename, const void *inf,
+		 const struct xt_match *match, void *matchinfo,
+		 unsigned int hook_mask)
+{
+        if (nf_ct_l3proto_try_module_get(match->family) < 0) {
+                printk(KERN_WARNING "can't load conntrack support for "
+                                    "proto=%d\n", match->family);
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
+		return -EINVAL;
+	}
+	return 0;
+#else
+                return 0;
+        }
+	return 1;
+#endif
+}
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
+	static void destroy(const struct xt_mtdtor_param *par)
+	{
+		nf_ct_l3proto_module_put(par->match->family);
+	}
+#else
+	static void destroy(const struct xt_match *match, void *matchinfo)
+	{
+		nf_ct_l3proto_module_put(match->family);
+	}
+#endif
+
+static struct xt_match xt_layer7_match[] __read_mostly = {
+{
+	.name		= "layer7",
+	.family		= AF_INET,
+	.checkentry	= check,
+	.match		= match,
+	.destroy	= destroy,
+	.matchsize	= sizeof(struct xt_layer7_info),
+	.me		= THIS_MODULE
+}
+};
+
+static void layer7_cleanup_proc(void)
+{
+	remove_proc_entry("layer7_numpackets", init_net.proc_net);
+}
+
+/* register the proc file */
+static void layer7_init_proc(void)
+{
+	struct proc_dir_entry* entry;
+	entry = create_proc_entry("layer7_numpackets", 0644, init_net.proc_net);
+	entry->read_proc = layer7_read_proc;
+	entry->write_proc = layer7_write_proc;
+}
+
+static int __init xt_layer7_init(void)
+{
+	need_conntrack();
+
+	layer7_init_proc();
+	if(maxdatalen < 1) {
+		printk(KERN_WARNING "layer7: maxdatalen can't be < 1, "
+			"using 1\n");
+		maxdatalen = 1;
+	}
+	/* This is not a hard limit.  It's just here to prevent people from
+	bringing their slow machines to a grinding halt. */
+	else if(maxdatalen > 65536) {
+		printk(KERN_WARNING "layer7: maxdatalen can't be > 65536, "
+			"using 65536\n");
+		maxdatalen = 65536;
+	}
+	return xt_register_matches(xt_layer7_match,
+				   ARRAY_SIZE(xt_layer7_match));
+}
+
+static void __exit xt_layer7_fini(void)
+{
+	layer7_cleanup_proc();
+	xt_unregister_matches(xt_layer7_match, ARRAY_SIZE(xt_layer7_match));
+}
+
+module_init(xt_layer7_init);
+module_exit(xt_layer7_fini);
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 467af9c..db7b344 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -854,25 +854,7 @@
 
 static struct sk_buff *netlink_trim(struct sk_buff *skb, gfp_t allocation)
 {
-	int delta;
-
 	skb_orphan(skb);
-
-	delta = skb->end - skb->tail;
-	if (delta * 2 < skb->truesize)
-		return skb;
-
-	if (skb_shared(skb)) {
-		struct sk_buff *nskb = skb_clone(skb, allocation);
-		if (!nskb)
-			return skb;
-		kfree_skb(skb);
-		skb = nskb;
-	}
-
-	if (!pskb_expand_head(skb, 0, -delta, allocation))
-		skb->truesize -= delta;
-
 	return skb;
 }
 
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 2dbb32b..a17a3c8 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -296,6 +296,7 @@
 	unsigned int		tp_loss:1;
 	unsigned int		tp_tstamp;
 	struct packet_type	prot_hook ____cacheline_aligned_in_smp;
+	unsigned int		pkt_type;
 };
 
 #define PACKET_FANOUT_MAX	256
@@ -1383,6 +1384,7 @@
 {
 	struct sock *sk;
 	struct sockaddr_pkt *spkt;
+	struct packet_sock *po;
 
 	/*
 	 *	When we registered the protocol we saved the socket in the data
@@ -1390,6 +1392,7 @@
 	 */
 
 	sk = pt->af_packet_priv;
+	po = pkt_sk(sk);
 
 	/*
 	 *	Yank back the headers [hope the device set this
@@ -1402,7 +1405,7 @@
 	 *	so that this procedure is noop.
 	 */
 
-	if (skb->pkt_type == PACKET_LOOPBACK)
+	if (!(po->pkt_type & (1 << skb->pkt_type)))
 		goto out;
 
 	if (!net_eq(dev_net(dev), sock_net(sk)))
@@ -1596,12 +1599,12 @@
 	int skb_len = skb->len;
 	unsigned int snaplen, res;
 
-	if (skb->pkt_type == PACKET_LOOPBACK)
-		goto drop;
-
 	sk = pt->af_packet_priv;
 	po = pkt_sk(sk);
 
+	if (!(po->pkt_type & (1 << skb->pkt_type)))
+		goto drop;
+
 	if (!net_eq(dev_net(dev), sock_net(sk)))
 		goto drop;
 
@@ -1720,12 +1723,12 @@
 	struct timespec ts;
 	struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);
 
-	if (skb->pkt_type == PACKET_LOOPBACK)
-		goto drop;
-
 	sk = pt->af_packet_priv;
 	po = pkt_sk(sk);
 
+	if (!(po->pkt_type & (1 << skb->pkt_type)))
+		goto drop;
+
 	if (!net_eq(dev_net(dev), sock_net(sk)))
 		goto drop;
 
@@ -2595,6 +2598,7 @@
 	spin_lock_init(&po->bind_lock);
 	mutex_init(&po->pg_vec_lock);
 	po->prot_hook.func = packet_rcv;
+	po->pkt_type = PACKET_MASK_ANY & ~(1 << PACKET_LOOPBACK);
 
 	if (sock->type == SOCK_PACKET)
 		po->prot_hook.func = packet_rcv_spkt;
@@ -3192,6 +3196,16 @@
 
 		return fanout_add(sk, val & 0xffff, val >> 16);
 	}
+        case PACKET_RECV_TYPE:
+        {
+                unsigned int val;
+                if (optlen != sizeof(val))
+                        return -EINVAL;
+                if (copy_from_user(&val, optval, sizeof(val)))
+                        return -EFAULT;
+                po->pkt_type = val & ~PACKET_LOOPBACK;
+                return 0;
+        }
 	default:
 		return -ENOPROTOOPT;
 	}
@@ -3262,6 +3276,13 @@
 
 		data = &val;
 		break;
+	case PACKET_RECV_TYPE:
+		if (len > sizeof(unsigned int))
+			len = sizeof(unsigned int);
+		val = po->pkt_type;
+
+		data = &val;
+		break;
 	case PACKET_VERSION:
 		if (len > sizeof(int))
 			len = sizeof(int);
diff --git a/net/sched/Kconfig b/net/sched/Kconfig
index 2590e91..905a1e3 100644
--- a/net/sched/Kconfig
+++ b/net/sched/Kconfig
@@ -148,6 +148,37 @@
 	  To compile this code as a module, choose M here: the
 	  module will be called sch_sfq.
 
+config NET_SCH_ESFQ
+	tristate "Enhanced Stochastic Fairness Queueing (ESFQ)"
+	---help---
+	  Say Y here if you want to use the Enhanced Stochastic Fairness
+	  Queueing (ESFQ) packet scheduling algorithm for some of your network
+	  devices or as a leaf discipline for a classful qdisc such as HTB or
+	  CBQ (see the top of <file:net/sched/sch_esfq.c> for details and
+	  references to the SFQ algorithm).
+
+	  This is an enchanced SFQ version which allows you to control some
+	  hardcoded values in the SFQ scheduler.
+
+	  ESFQ also adds control of the hash function used to identify packet
+	  flows. The original SFQ discipline hashes by connection; ESFQ add
+	  several other hashing methods, such as by src IP or by dst IP, which
+	  can be more fair to users in some networking situations.
+
+	  To compile this code as a module, choose M here: the
+	  module will be called sch_esfq.
+
+config NET_SCH_ESFQ_NFCT
+	bool "Connection Tracking Hash Types"
+	depends on NET_SCH_ESFQ && NF_CONNTRACK
+	---help---
+	  Say Y here to enable support for hashing based on netfilter connection
+	  tracking information. This is useful for a router that is also using
+	  NAT to connect privately-addressed hosts to the Internet. If you want
+	  to provide fair distribution of upstream bandwidth, ESFQ must use
+	  connection tracking information, since all outgoing packets will share
+	  the same source address.
+
 config NET_SCH_TEQL
 	tristate "True Link Equalizer (TEQL)"
 	---help---
@@ -250,6 +281,28 @@
 
 	  If unsure, say N.
 
+config NET_SCH_CODEL
+	tristate "Controlled Delay AQM (CODEL)"
+	help
+	  Say Y here if you want to use the Controlled Delay (CODEL)
+	  packet scheduling algorithm.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called sch_codel.
+
+	  If unsure, say N.
+
+config NET_SCH_FQ_CODEL
+	tristate "Fair Queue Controlled Delay AQM (FQ_CODEL)"
+	help
+	  Say Y here if you want to use the FQ Controlled Delay (FQ_CODEL)
+	  packet scheduling algorithm.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called sch_fq_codel.
+
+	  If unsure, say N.
+
 config NET_SCH_INGRESS
 	tristate "Ingress Qdisc"
 	depends on NET_CLS_ACT
@@ -571,6 +624,19 @@
 	  To compile this code as a module, choose M here: the
 	  module will be called act_csum.
 
+config NET_ACT_CONNMARK
+        tristate "Connection Tracking Marking"
+        depends on NET_CLS_ACT
+        depends on NF_CONNTRACK
+	 depends on NF_CONNTRACK_MARK
+        ---help---
+	  Say Y here to restore the connmark from a scheduler action
+
+	  If unsure, say N.
+
+	  To compile this code as a module, choose M here: the
+	  module will be called act_connmark.
+
 config NET_CLS_IND
 	bool "Incoming device classification"
 	depends on NET_CLS_U32 || NET_CLS_FW
diff --git a/net/sched/Makefile b/net/sched/Makefile
index dc5889c..88d923b 100644
--- a/net/sched/Makefile
+++ b/net/sched/Makefile
@@ -16,6 +16,7 @@
 obj-$(CONFIG_NET_ACT_SIMP)	+= act_simple.o
 obj-$(CONFIG_NET_ACT_SKBEDIT)	+= act_skbedit.o
 obj-$(CONFIG_NET_ACT_CSUM)	+= act_csum.o
+obj-$(CONFIG_NET_ACT_CONNMARK)	+= act_connmark.o
 obj-$(CONFIG_NET_SCH_FIFO)	+= sch_fifo.o
 obj-$(CONFIG_NET_SCH_CBQ)	+= sch_cbq.o
 obj-$(CONFIG_NET_SCH_HTB)	+= sch_htb.o
@@ -26,6 +27,7 @@
 obj-$(CONFIG_NET_SCH_DSMARK)	+= sch_dsmark.o
 obj-$(CONFIG_NET_SCH_SFB)	+= sch_sfb.o
 obj-$(CONFIG_NET_SCH_SFQ)	+= sch_sfq.o
+obj-$(CONFIG_NET_SCH_ESFQ)	+= sch_esfq.o
 obj-$(CONFIG_NET_SCH_TBF)	+= sch_tbf.o
 obj-$(CONFIG_NET_SCH_TEQL)	+= sch_teql.o
 obj-$(CONFIG_NET_SCH_PRIO)	+= sch_prio.o
@@ -36,6 +38,8 @@
 obj-$(CONFIG_NET_SCH_MQPRIO)	+= sch_mqprio.o
 obj-$(CONFIG_NET_SCH_CHOKE)	+= sch_choke.o
 obj-$(CONFIG_NET_SCH_QFQ)	+= sch_qfq.o
+obj-$(CONFIG_NET_SCH_CODEL)	+= sch_codel.o
+obj-$(CONFIG_NET_SCH_FQ_CODEL)	+= sch_fq_codel.o
 
 obj-$(CONFIG_NET_CLS_U32)	+= cls_u32.o
 obj-$(CONFIG_NET_CLS_ROUTE4)	+= cls_route.o
diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c
new file mode 100644
index 0000000..79880f7
--- /dev/null
+++ b/net/sched/act_connmark.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2011 Felix Fietkau <nbd@openwrt.org>
+ *
+ * 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., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <linux/rtnetlink.h>
+#include <linux/pkt_cls.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <net/netlink.h>
+#include <net/pkt_sched.h>
+#include <net/act_api.h>
+
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_core.h>
+
+#define TCA_ACT_CONNMARK	20
+
+#define CONNMARK_TAB_MASK     3
+static struct tcf_common *tcf_connmark_ht[CONNMARK_TAB_MASK + 1];
+static u32 connmark_idx_gen;
+static DEFINE_RWLOCK(connmark_lock);
+
+static struct tcf_hashinfo connmark_hash_info = {
+	.htab	=	tcf_connmark_ht,
+	.hmask	=	CONNMARK_TAB_MASK,
+	.lock	=	&connmark_lock,
+};
+
+static int tcf_connmark(struct sk_buff *skb, const struct tc_action *a,
+		       struct tcf_result *res)
+{
+	struct nf_conn *c;
+	enum ip_conntrack_info ctinfo;
+	int proto;
+	int r;
+
+	if (skb->protocol == htons(ETH_P_IP)) {
+		if (skb->len < sizeof(struct iphdr))
+			goto out;
+		proto = PF_INET;
+	} else if (skb->protocol == htons(ETH_P_IPV6)) {
+		if (skb->len < sizeof(struct ipv6hdr))
+			goto out;
+		proto = PF_INET6;
+	} else
+		goto out;
+
+	r = nf_conntrack_in(dev_net(skb->dev), proto, NF_INET_PRE_ROUTING, skb);
+	if (r != NF_ACCEPT)
+		goto out;
+
+	c = nf_ct_get(skb, &ctinfo);
+	if (!c)
+		goto out;
+
+	skb->mark = c->mark;
+	nf_conntrack_put(skb->nfct);
+	skb->nfct = NULL;
+
+out:
+	return TC_ACT_PIPE;
+}
+
+static int tcf_connmark_init(struct nlattr *nla, struct nlattr *est,
+			 struct tc_action *a, int ovr, int bind)
+{
+	struct tcf_common *pc;
+
+	pc = tcf_hash_create(0, est, a, sizeof(*pc), bind,
+			     &connmark_idx_gen, &connmark_hash_info);
+	if (IS_ERR(pc))
+	    return PTR_ERR(pc);
+
+	tcf_hash_insert(pc, &connmark_hash_info);
+
+	return ACT_P_CREATED;
+}
+
+static inline int tcf_connmark_cleanup(struct tc_action *a, int bind)
+{
+	if (a->priv)
+		return tcf_hash_release(a->priv, bind, &connmark_hash_info);
+	return 0;
+}
+
+static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a,
+				int bind, int ref)
+{
+	return skb->len;
+}
+
+static struct tc_action_ops act_connmark_ops = {
+	.kind		=	"connmark",
+	.hinfo		=	&connmark_hash_info,
+	.type		=	TCA_ACT_CONNMARK,
+	.capab		=	TCA_CAP_NONE,
+	.owner		=	THIS_MODULE,
+	.act		=	tcf_connmark,
+	.dump		=	tcf_connmark_dump,
+	.cleanup	=	tcf_connmark_cleanup,
+	.init		=	tcf_connmark_init,
+	.walk		=	tcf_generic_walker,
+};
+
+MODULE_AUTHOR("Felix Fietkau <nbd@openwrt.org>");
+MODULE_DESCRIPTION("Connection tracking mark restoring");
+MODULE_LICENSE("GPL");
+
+static int __init connmark_init_module(void)
+{
+	return tcf_register_action(&act_connmark_ops);
+}
+
+static void __exit connmark_cleanup_module(void)
+{
+	tcf_unregister_action(&act_connmark_ops);
+}
+
+module_init(connmark_init_module);
+module_exit(connmark_cleanup_module);
diff --git a/net/sched/sch_codel.c b/net/sched/sch_codel.c
new file mode 100644
index 0000000..2f9ab17
--- /dev/null
+++ b/net/sched/sch_codel.c
@@ -0,0 +1,276 @@
+/*
+ * Codel - The Controlled-Delay Active Queue Management algorithm
+ *
+ *  Copyright (C) 2011-2012 Kathleen Nichols <nichols@pollere.com>
+ *  Copyright (C) 2011-2012 Van Jacobson <van@pollere.net>
+ *
+ *  Implemented on linux by :
+ *  Copyright (C) 2012 Michael D. Taht <dave.taht@bufferbloat.net>
+ *  Copyright (C) 2012 Eric Dumazet <edumazet@google.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The names of the authors may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, provided that this notice is retained in full, this
+ * software may be distributed under the terms of the GNU General
+ * Public License ("GPL") version 2, in which case the provisions of the
+ * GPL apply INSTEAD OF those given above.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/skbuff.h>
+#include <linux/prefetch.h>
+#include <net/pkt_sched.h>
+#include <net/codel.h>
+
+
+#define DEFAULT_CODEL_LIMIT 1000
+
+struct codel_sched_data {
+	struct codel_params	params;
+	struct codel_vars	vars;
+	struct codel_stats	stats;
+	u32			drop_overlimit;
+};
+
+/* This is the specific function called from codel_dequeue()
+ * to dequeue a packet from queue. Note: backlog is handled in
+ * codel, we dont need to reduce it here.
+ */
+static struct sk_buff *dequeue(struct codel_vars *vars, struct Qdisc *sch)
+{
+	struct sk_buff *skb = __skb_dequeue(&sch->q);
+
+	prefetch(&skb->end); /* we'll need skb_shinfo() */
+	return skb;
+}
+
+static struct sk_buff *codel_qdisc_dequeue(struct Qdisc *sch)
+{
+	struct codel_sched_data *q = qdisc_priv(sch);
+	struct sk_buff *skb;
+
+	skb = codel_dequeue(sch, &q->params, &q->vars, &q->stats, dequeue);
+
+	/* We cant call qdisc_tree_decrease_qlen() if our qlen is 0,
+	 * or HTB crashes. Defer it for next round.
+	 */
+	if (q->stats.drop_count && sch->q.qlen) {
+		qdisc_tree_decrease_qlen(sch, q->stats.drop_count);
+		q->stats.drop_count = 0;
+	}
+	if (skb)
+		qdisc_bstats_update(sch, skb);
+	return skb;
+}
+
+static int codel_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch)
+{
+	struct codel_sched_data *q;
+
+	if (likely(qdisc_qlen(sch) < sch->limit)) {
+		codel_set_enqueue_time(skb);
+		return qdisc_enqueue_tail(skb, sch);
+	}
+	q = qdisc_priv(sch);
+	q->drop_overlimit++;
+	return qdisc_drop(skb, sch);
+}
+
+static const struct nla_policy codel_policy[TCA_CODEL_MAX + 1] = {
+	[TCA_CODEL_TARGET]	= { .type = NLA_U32 },
+	[TCA_CODEL_LIMIT]	= { .type = NLA_U32 },
+	[TCA_CODEL_INTERVAL]	= { .type = NLA_U32 },
+	[TCA_CODEL_ECN]		= { .type = NLA_U32 },
+};
+
+static int codel_change(struct Qdisc *sch, struct nlattr *opt)
+{
+	struct codel_sched_data *q = qdisc_priv(sch);
+	struct nlattr *tb[TCA_CODEL_MAX + 1];
+	unsigned int qlen;
+	int err;
+
+	if (!opt)
+		return -EINVAL;
+
+	err = nla_parse_nested(tb, TCA_CODEL_MAX, opt, codel_policy);
+	if (err < 0)
+		return err;
+
+	sch_tree_lock(sch);
+
+	if (tb[TCA_CODEL_TARGET]) {
+		u32 target = nla_get_u32(tb[TCA_CODEL_TARGET]);
+
+		q->params.target = ((u64)target * NSEC_PER_USEC) >> CODEL_SHIFT;
+	}
+
+	if (tb[TCA_CODEL_INTERVAL]) {
+		u32 interval = nla_get_u32(tb[TCA_CODEL_INTERVAL]);
+
+		q->params.interval = ((u64)interval * NSEC_PER_USEC) >> CODEL_SHIFT;
+	}
+
+	if (tb[TCA_CODEL_LIMIT])
+		sch->limit = nla_get_u32(tb[TCA_CODEL_LIMIT]);
+
+	if (tb[TCA_CODEL_ECN])
+		q->params.ecn = !!nla_get_u32(tb[TCA_CODEL_ECN]);
+
+	qlen = sch->q.qlen;
+	while (sch->q.qlen > sch->limit) {
+		struct sk_buff *skb = __skb_dequeue(&sch->q);
+
+		sch->qstats.backlog -= qdisc_pkt_len(skb);
+		qdisc_drop(skb, sch);
+	}
+	qdisc_tree_decrease_qlen(sch, qlen - sch->q.qlen);
+
+	sch_tree_unlock(sch);
+	return 0;
+}
+
+static int codel_init(struct Qdisc *sch, struct nlattr *opt)
+{
+	struct codel_sched_data *q = qdisc_priv(sch);
+
+	sch->limit = DEFAULT_CODEL_LIMIT;
+
+	codel_params_init(&q->params);
+	codel_vars_init(&q->vars);
+	codel_stats_init(&q->stats);
+
+	if (opt) {
+		int err = codel_change(sch, opt);
+
+		if (err)
+			return err;
+	}
+
+	if (sch->limit >= 1)
+		sch->flags |= TCQ_F_CAN_BYPASS;
+	else
+		sch->flags &= ~TCQ_F_CAN_BYPASS;
+
+	return 0;
+}
+
+static int codel_dump(struct Qdisc *sch, struct sk_buff *skb)
+{
+	struct codel_sched_data *q = qdisc_priv(sch);
+	struct nlattr *opts;
+
+	opts = nla_nest_start(skb, TCA_OPTIONS);
+	if (opts == NULL)
+		goto nla_put_failure;
+
+	if (nla_put_u32(skb, TCA_CODEL_TARGET,
+			codel_time_to_us(q->params.target)) ||
+	    nla_put_u32(skb, TCA_CODEL_LIMIT,
+			sch->limit) ||
+	    nla_put_u32(skb, TCA_CODEL_INTERVAL,
+			codel_time_to_us(q->params.interval)) ||
+	    nla_put_u32(skb, TCA_CODEL_ECN,
+			q->params.ecn))
+		goto nla_put_failure;
+
+	return nla_nest_end(skb, opts);
+
+nla_put_failure:
+	nla_nest_cancel(skb, opts);
+	return -1;
+}
+
+static int codel_dump_stats(struct Qdisc *sch, struct gnet_dump *d)
+{
+	const struct codel_sched_data *q = qdisc_priv(sch);
+	struct tc_codel_xstats st = {
+		.maxpacket	= q->stats.maxpacket,
+		.count		= q->vars.count,
+		.lastcount	= q->vars.lastcount,
+		.drop_overlimit = q->drop_overlimit,
+		.ldelay		= codel_time_to_us(q->vars.ldelay),
+		.dropping	= q->vars.dropping,
+		.ecn_mark	= q->stats.ecn_mark,
+	};
+
+	if (q->vars.dropping) {
+		codel_tdiff_t delta = q->vars.drop_next - codel_get_time();
+
+		if (delta >= 0)
+			st.drop_next = codel_time_to_us(delta);
+		else
+			st.drop_next = -codel_time_to_us(-delta);
+	}
+
+	return gnet_stats_copy_app(d, &st, sizeof(st));
+}
+
+static void codel_reset(struct Qdisc *sch)
+{
+	struct codel_sched_data *q = qdisc_priv(sch);
+
+	qdisc_reset_queue(sch);
+	codel_vars_init(&q->vars);
+}
+
+static struct Qdisc_ops codel_qdisc_ops __read_mostly = {
+	.id		=	"codel",
+	.priv_size	=	sizeof(struct codel_sched_data),
+
+	.enqueue	=	codel_qdisc_enqueue,
+	.dequeue	=	codel_qdisc_dequeue,
+	.peek		=	qdisc_peek_dequeued,
+	.init		=	codel_init,
+	.reset		=	codel_reset,
+	.change 	=	codel_change,
+	.dump		=	codel_dump,
+	.dump_stats	=	codel_dump_stats,
+	.owner		=	THIS_MODULE,
+};
+
+static int __init codel_module_init(void)
+{
+	return register_qdisc(&codel_qdisc_ops);
+}
+
+static void __exit codel_module_exit(void)
+{
+	unregister_qdisc(&codel_qdisc_ops);
+}
+
+module_init(codel_module_init)
+module_exit(codel_module_exit)
+
+MODULE_DESCRIPTION("Controlled Delay queue discipline");
+MODULE_AUTHOR("Dave Taht");
+MODULE_AUTHOR("Eric Dumazet");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/net/sched/sch_esfq.c b/net/sched/sch_esfq.c
new file mode 100644
index 0000000..6618a74
--- /dev/null
+++ b/net/sched/sch_esfq.c
@@ -0,0 +1,702 @@
+/*
+ * net/sched/sch_esfq.c	Extended Stochastic Fairness Queueing discipline.
+ *
+ *		This program is free software; you can redistribute it and/or
+ *		modify it under the terms of the GNU General Public License
+ *		as published by the Free Software Foundation; either version
+ *		2 of the License, or (at your option) any later version.
+ *
+ * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ *
+ * Changes:	Alexander Atanasov, <alex@ssi.bg>
+ *		Added dynamic depth,limit,divisor,hash_kind options.
+ *		Added dst and src hashes.
+ *
+ * 		Alexander Clouter, <alex@digriz.org.uk>
+ *		Ported ESFQ to Linux 2.6.
+ *
+ * 		Corey Hickey, <bugfood-c@fatooh.org>
+ *		Maintenance of the Linux 2.6 port.
+ *		Added fwmark hash (thanks to Robert Kurjata).
+ *		Added usage of jhash.
+ *		Added conntrack support.
+ *		Added ctnatchg hash (thanks to Ben Pfountz).
+ */
+
+#include <linux/module.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <linux/bitops.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/jiffies.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/in.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/if_ether.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/notifier.h>
+#include <linux/init.h>
+#include <net/ip.h>
+#include <net/netlink.h>
+#include <linux/ipv6.h>
+#include <net/route.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <net/pkt_sched.h>
+#include <linux/jhash.h>
+#ifdef CONFIG_NET_SCH_ESFQ_NFCT
+#include <net/netfilter/nf_conntrack.h>
+#endif
+
+/*	Stochastic Fairness Queuing algorithm.
+	For more comments look at sch_sfq.c.
+	The difference is that you can change limit, depth,
+	hash table size and choose alternate hash types.
+
+	classic:	same as in sch_sfq.c
+	dst:		destination IP address
+	src:		source IP address
+	fwmark:		netfilter mark value
+	ctorigdst:	original destination IP address
+	ctorigsrc:	original source IP address
+	ctrepldst:	reply destination IP address
+	ctreplsrc:	reply source IP
+
+*/
+
+#define ESFQ_HEAD 0
+#define ESFQ_TAIL 1
+
+/* This type should contain at least SFQ_DEPTH*2 values */
+typedef unsigned int esfq_index;
+
+struct esfq_head
+{
+	esfq_index	next;
+	esfq_index	prev;
+};
+
+struct esfq_sched_data
+{
+/* Parameters */
+	int		perturb_period;
+	unsigned	quantum;	/* Allotment per round: MUST BE >= MTU */
+	int		limit;
+	unsigned	depth;
+	unsigned	hash_divisor;
+	unsigned	hash_kind;
+/* Variables */
+	struct timer_list perturb_timer;
+	int		perturbation;
+	esfq_index	tail;		/* Index of current slot in round */
+	esfq_index	max_depth;	/* Maximal depth */
+
+	esfq_index	*ht;			/* Hash table */
+	esfq_index	*next;			/* Active slots link */
+	short		*allot;			/* Current allotment per slot */
+	unsigned short	*hash;			/* Hash value indexed by slots */
+	struct sk_buff_head	*qs;		/* Slot queue */
+	struct esfq_head	*dep;		/* Linked list of slots, indexed by depth */
+};
+
+/* This contains the info we will hash. */
+struct esfq_packet_info
+{
+	u32	proto;		/* protocol or port */
+	u32	src;		/* source from packet header */
+	u32	dst;		/* destination from packet header */
+	u32	ctorigsrc;	/* original source from conntrack */
+	u32	ctorigdst;	/* original destination from conntrack */
+	u32	ctreplsrc;	/* reply source from conntrack */
+	u32	ctrepldst;	/* reply destination from conntrack */
+	u32	mark;		/* netfilter mark (fwmark) */
+};
+
+static __inline__ unsigned esfq_jhash_1word(struct esfq_sched_data *q,u32 a)
+{
+	return jhash_1word(a, q->perturbation) & (q->hash_divisor-1);
+}
+
+static __inline__ unsigned esfq_jhash_2words(struct esfq_sched_data *q, u32 a, u32 b)
+{
+	return jhash_2words(a, b, q->perturbation) & (q->hash_divisor-1);
+}
+
+static __inline__ unsigned esfq_jhash_3words(struct esfq_sched_data *q, u32 a, u32 b, u32 c)
+{
+	return jhash_3words(a, b, c, q->perturbation) & (q->hash_divisor-1);
+}
+
+static unsigned esfq_hash(struct esfq_sched_data *q, struct sk_buff *skb)
+{
+	struct esfq_packet_info info;
+#ifdef CONFIG_NET_SCH_ESFQ_NFCT
+	enum ip_conntrack_info ctinfo;
+	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
+#endif
+
+	switch (skb->protocol) {
+	case __constant_htons(ETH_P_IP):
+	{
+		struct iphdr *iph = ip_hdr(skb);
+		info.dst = iph->daddr;
+		info.src = iph->saddr;
+		if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) &&
+		    (iph->protocol == IPPROTO_TCP ||
+		     iph->protocol == IPPROTO_UDP ||
+		     iph->protocol == IPPROTO_SCTP ||
+		     iph->protocol == IPPROTO_DCCP ||
+		     iph->protocol == IPPROTO_ESP))
+			info.proto = *(((u32*)iph) + iph->ihl);
+		else
+			info.proto = iph->protocol;
+		break;
+	}
+	case __constant_htons(ETH_P_IPV6):
+	{
+		struct ipv6hdr *iph = ipv6_hdr(skb);
+		/* Hash ipv6 addresses into a u32. This isn't ideal,
+		 * but the code is simple. */
+		info.dst = jhash2(iph->daddr.s6_addr32, 4, q->perturbation);
+		info.src = jhash2(iph->saddr.s6_addr32, 4, q->perturbation);
+		if (iph->nexthdr == IPPROTO_TCP ||
+		    iph->nexthdr == IPPROTO_UDP ||
+		    iph->nexthdr == IPPROTO_SCTP ||
+		    iph->nexthdr == IPPROTO_DCCP ||
+		    iph->nexthdr == IPPROTO_ESP)
+			info.proto = *(u32*)&iph[1];
+		else
+			info.proto = iph->nexthdr;
+		break;
+	}
+	default:
+		info.dst   = (u32)(unsigned long)skb_dst(skb);
+		info.src   = (u32)(unsigned long)skb->sk;
+		info.proto = skb->protocol;
+	}
+
+	info.mark = skb->mark;
+
+#ifdef CONFIG_NET_SCH_ESFQ_NFCT
+	/* defaults if there is no conntrack info */
+	info.ctorigsrc = info.src;
+	info.ctorigdst = info.dst;
+	info.ctreplsrc = info.dst;
+	info.ctrepldst = info.src;
+	/* collect conntrack info */
+	if (ct && ct != &nf_conntrack_untracked) {
+		if (skb->protocol == __constant_htons(ETH_P_IP)) {
+			info.ctorigsrc = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip;
+			info.ctorigdst = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip;
+			info.ctreplsrc = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip;
+			info.ctrepldst = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip;
+		}
+		else if (skb->protocol == __constant_htons(ETH_P_IPV6)) {
+			/* Again, hash ipv6 addresses into a single u32. */
+			info.ctorigsrc = jhash2(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip6, 4, q->perturbation);
+			info.ctorigdst = jhash2(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip6, 4, q->perturbation);
+			info.ctreplsrc = jhash2(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip6, 4, q->perturbation);
+			info.ctrepldst = jhash2(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip6, 4, q->perturbation);
+		}
+
+	}
+#endif
+
+	switch(q->hash_kind) {
+	case TCA_SFQ_HASH_CLASSIC:
+		return esfq_jhash_3words(q, info.dst, info.src, info.proto);
+	case TCA_SFQ_HASH_DST:
+		return esfq_jhash_1word(q, info.dst);
+	case TCA_SFQ_HASH_SRC:
+		return esfq_jhash_1word(q, info.src);
+	case TCA_SFQ_HASH_FWMARK:
+		return esfq_jhash_1word(q, info.mark);
+#ifdef CONFIG_NET_SCH_ESFQ_NFCT
+	case TCA_SFQ_HASH_CTORIGDST:
+		return esfq_jhash_1word(q, info.ctorigdst);
+	case TCA_SFQ_HASH_CTORIGSRC:
+		return esfq_jhash_1word(q, info.ctorigsrc);
+	case TCA_SFQ_HASH_CTREPLDST:
+		return esfq_jhash_1word(q, info.ctrepldst);
+	case TCA_SFQ_HASH_CTREPLSRC:
+		return esfq_jhash_1word(q, info.ctreplsrc);
+	case TCA_SFQ_HASH_CTNATCHG:
+	{
+		if (info.ctorigdst == info.ctreplsrc)
+			return esfq_jhash_1word(q, info.ctorigsrc);
+		return esfq_jhash_1word(q, info.ctreplsrc);
+	}
+#endif
+	default:
+		if (net_ratelimit())
+			printk(KERN_WARNING "ESFQ: Unknown hash method. Falling back to classic.\n");
+	}
+	return esfq_jhash_3words(q, info.dst, info.src, info.proto);
+}
+
+static inline void esfq_link(struct esfq_sched_data *q, esfq_index x)
+{
+	esfq_index p, n;
+	int d = q->qs[x].qlen + q->depth;
+
+	p = d;
+	n = q->dep[d].next;
+	q->dep[x].next = n;
+	q->dep[x].prev = p;
+	q->dep[p].next = q->dep[n].prev = x;
+}
+
+static inline void esfq_dec(struct esfq_sched_data *q, esfq_index x)
+{
+	esfq_index p, n;
+
+	n = q->dep[x].next;
+	p = q->dep[x].prev;
+	q->dep[p].next = n;
+	q->dep[n].prev = p;
+
+	if (n == p && q->max_depth == q->qs[x].qlen + 1)
+		q->max_depth--;
+
+	esfq_link(q, x);
+}
+
+static inline void esfq_inc(struct esfq_sched_data *q, esfq_index x)
+{
+	esfq_index p, n;
+	int d;
+
+	n = q->dep[x].next;
+	p = q->dep[x].prev;
+	q->dep[p].next = n;
+	q->dep[n].prev = p;
+	d = q->qs[x].qlen;
+	if (q->max_depth < d)
+		q->max_depth = d;
+
+	esfq_link(q, x);
+}
+
+static unsigned int esfq_drop(struct Qdisc *sch)
+{
+	struct esfq_sched_data *q = qdisc_priv(sch);
+	esfq_index d = q->max_depth;
+	struct sk_buff *skb;
+	unsigned int len;
+
+	/* Queue is full! Find the longest slot and
+	   drop a packet from it */
+
+	if (d > 1) {
+		esfq_index x = q->dep[d+q->depth].next;
+		skb = q->qs[x].prev;
+		len = skb->len;
+		__skb_unlink(skb, &q->qs[x]);
+		kfree_skb(skb);
+		esfq_dec(q, x);
+		sch->q.qlen--;
+		sch->qstats.drops++;
+		sch->qstats.backlog -= len;
+		return len;
+	}
+
+	if (d == 1) {
+		/* It is difficult to believe, but ALL THE SLOTS HAVE LENGTH 1. */
+		d = q->next[q->tail];
+		q->next[q->tail] = q->next[d];
+		q->allot[q->next[d]] += q->quantum;
+		skb = q->qs[d].prev;
+		len = skb->len;
+		__skb_unlink(skb, &q->qs[d]);
+		kfree_skb(skb);
+		esfq_dec(q, d);
+		sch->q.qlen--;
+		q->ht[q->hash[d]] = q->depth;
+		sch->qstats.drops++;
+		sch->qstats.backlog -= len;
+		return len;
+	}
+
+	return 0;
+}
+
+static void esfq_q_enqueue(struct sk_buff *skb, struct esfq_sched_data *q, unsigned int end)
+{
+	unsigned hash = esfq_hash(q, skb);
+	unsigned depth = q->depth;
+	esfq_index x;
+
+	x = q->ht[hash];
+	if (x == depth) {
+		q->ht[hash] = x = q->dep[depth].next;
+		q->hash[x] = hash;
+	}
+
+	if (end == ESFQ_TAIL)
+		__skb_queue_tail(&q->qs[x], skb);
+	else
+		__skb_queue_head(&q->qs[x], skb);
+
+	esfq_inc(q, x);
+	if (q->qs[x].qlen == 1) {		/* The flow is new */
+		if (q->tail == depth) {	/* It is the first flow */
+			q->tail = x;
+			q->next[x] = x;
+			q->allot[x] = q->quantum;
+		} else {
+			q->next[x] = q->next[q->tail];
+			q->next[q->tail] = x;
+			q->tail = x;
+		}
+	}
+}
+
+static int esfq_enqueue(struct sk_buff *skb, struct Qdisc* sch)
+{
+	struct esfq_sched_data *q = qdisc_priv(sch);
+	esfq_q_enqueue(skb, q, ESFQ_TAIL);
+	sch->qstats.backlog += skb->len;
+	if (++sch->q.qlen < q->limit-1) {
+		sch->bstats.bytes += skb->len;
+		sch->bstats.packets++;
+		return 0;
+	}
+
+	sch->qstats.drops++;
+	esfq_drop(sch);
+	return NET_XMIT_CN;
+}
+
+static struct sk_buff *esfq_peek(struct Qdisc* sch)
+{
+	struct esfq_sched_data *q = qdisc_priv(sch);
+	esfq_index a;
+
+	/* No active slots */
+	if (q->tail == q->depth)
+		return NULL;
+
+	a = q->next[q->tail];
+	return skb_peek(&q->qs[a]);
+}
+
+static struct sk_buff *esfq_q_dequeue(struct esfq_sched_data *q)
+{
+	struct sk_buff *skb;
+	unsigned depth = q->depth;
+	esfq_index a, old_a;
+
+	/* No active slots */
+	if (q->tail == depth)
+		return NULL;
+
+	a = old_a = q->next[q->tail];
+
+	/* Grab packet */
+	skb = __skb_dequeue(&q->qs[a]);
+	esfq_dec(q, a);
+
+	/* Is the slot empty? */
+	if (q->qs[a].qlen == 0) {
+		q->ht[q->hash[a]] = depth;
+		a = q->next[a];
+		if (a == old_a) {
+			q->tail = depth;
+			return skb;
+		}
+		q->next[q->tail] = a;
+		q->allot[a] += q->quantum;
+	} else if ((q->allot[a] -= skb->len) <= 0) {
+		q->tail = a;
+		a = q->next[a];
+		q->allot[a] += q->quantum;
+	}
+
+	return skb;
+}
+
+static struct sk_buff *esfq_dequeue(struct Qdisc* sch)
+{
+	struct esfq_sched_data *q = qdisc_priv(sch);
+	struct sk_buff *skb;
+
+	skb = esfq_q_dequeue(q);
+	if (skb == NULL)
+		return NULL;
+	sch->q.qlen--;
+	sch->qstats.backlog -= skb->len;
+	return skb;
+}
+
+static void esfq_q_destroy(struct esfq_sched_data *q)
+{
+	del_timer(&q->perturb_timer);
+	if(q->ht)
+		kfree(q->ht);
+	if(q->dep)
+		kfree(q->dep);
+	if(q->next)
+		kfree(q->next);
+	if(q->allot)
+		kfree(q->allot);
+	if(q->hash)
+		kfree(q->hash);
+	if(q->qs)
+		kfree(q->qs);
+}
+
+static void esfq_destroy(struct Qdisc *sch)
+{
+	struct esfq_sched_data *q = qdisc_priv(sch);
+	esfq_q_destroy(q);
+}
+
+
+static void esfq_reset(struct Qdisc* sch)
+{
+	struct sk_buff *skb;
+
+	while ((skb = esfq_dequeue(sch)) != NULL)
+		kfree_skb(skb);
+}
+
+static void esfq_perturbation(unsigned long arg)
+{
+	struct Qdisc *sch = (struct Qdisc*)arg;
+	struct esfq_sched_data *q = qdisc_priv(sch);
+
+	q->perturbation = net_random()&0x1F;
+
+	if (q->perturb_period) {
+		q->perturb_timer.expires = jiffies + q->perturb_period;
+		add_timer(&q->perturb_timer);
+	}
+}
+
+static unsigned int esfq_check_hash(unsigned int kind)
+{
+	switch (kind) {
+	case TCA_SFQ_HASH_CTORIGDST:
+	case TCA_SFQ_HASH_CTORIGSRC:
+	case TCA_SFQ_HASH_CTREPLDST:
+	case TCA_SFQ_HASH_CTREPLSRC:
+	case TCA_SFQ_HASH_CTNATCHG:
+#ifndef CONFIG_NET_SCH_ESFQ_NFCT
+	{
+		if (net_ratelimit())
+			printk(KERN_WARNING "ESFQ: Conntrack hash types disabled in kernel config. Falling back to classic.\n");
+		return TCA_SFQ_HASH_CLASSIC;
+	}
+#endif
+	case TCA_SFQ_HASH_CLASSIC:
+	case TCA_SFQ_HASH_DST:
+	case TCA_SFQ_HASH_SRC:
+	case TCA_SFQ_HASH_FWMARK:
+		return kind;
+	default:
+	{
+		if (net_ratelimit())
+			printk(KERN_WARNING "ESFQ: Unknown hash type. Falling back to classic.\n");
+		return TCA_SFQ_HASH_CLASSIC;
+	}
+	}
+}
+
+static int esfq_q_init(struct esfq_sched_data *q, struct nlattr *opt)
+{
+	struct tc_esfq_qopt *ctl = nla_data(opt);
+	esfq_index p = ~0U/2;
+	int i;
+
+	if (opt && opt->nla_len < nla_attr_size(sizeof(*ctl)))
+		return -EINVAL;
+
+	q->perturbation = 0;
+	q->hash_kind = TCA_SFQ_HASH_CLASSIC;
+	q->max_depth = 0;
+	if (opt == NULL) {
+		q->perturb_period = 0;
+		q->hash_divisor = 1024;
+		q->tail = q->limit = q->depth = 128;
+
+	} else {
+		struct tc_esfq_qopt *ctl = nla_data(opt);
+		if (ctl->quantum)
+			q->quantum = ctl->quantum;
+		q->perturb_period = ctl->perturb_period*HZ;
+		q->hash_divisor = ctl->divisor ? : 1024;
+		q->tail = q->limit = q->depth = ctl->flows ? : 128;
+
+		if ( q->depth > p - 1 )
+			return -EINVAL;
+
+		if (ctl->limit)
+			q->limit = min_t(u32, ctl->limit, q->depth);
+
+		if (ctl->hash_kind) {
+			q->hash_kind = esfq_check_hash(ctl->hash_kind);
+		}
+	}
+
+	q->ht = kmalloc(q->hash_divisor*sizeof(esfq_index), GFP_KERNEL);
+	if (!q->ht)
+		goto err_case;
+	q->dep = kmalloc((1+q->depth*2)*sizeof(struct esfq_head), GFP_KERNEL);
+	if (!q->dep)
+		goto err_case;
+	q->next = kmalloc(q->depth*sizeof(esfq_index), GFP_KERNEL);
+	if (!q->next)
+		goto err_case;
+	q->allot = kmalloc(q->depth*sizeof(short), GFP_KERNEL);
+	if (!q->allot)
+		goto err_case;
+	q->hash = kmalloc(q->depth*sizeof(unsigned short), GFP_KERNEL);
+	if (!q->hash)
+		goto err_case;
+	q->qs = kmalloc(q->depth*sizeof(struct sk_buff_head), GFP_KERNEL);
+	if (!q->qs)
+		goto err_case;
+
+	for (i=0; i< q->hash_divisor; i++)
+		q->ht[i] = q->depth;
+	for (i=0; i<q->depth; i++) {
+		skb_queue_head_init(&q->qs[i]);
+		q->dep[i+q->depth].next = i+q->depth;
+		q->dep[i+q->depth].prev = i+q->depth;
+	}
+
+	for (i=0; i<q->depth; i++)
+		esfq_link(q, i);
+	return 0;
+err_case:
+	esfq_q_destroy(q);
+	return -ENOBUFS;
+}
+
+static int esfq_init(struct Qdisc *sch, struct nlattr *opt)
+{
+	struct esfq_sched_data *q = qdisc_priv(sch);
+	int err;
+
+	q->quantum = psched_mtu(qdisc_dev(sch)); /* default */
+	if ((err = esfq_q_init(q, opt)))
+		return err;
+
+	init_timer(&q->perturb_timer);
+	q->perturb_timer.data = (unsigned long)sch;
+	q->perturb_timer.function = esfq_perturbation;
+	if (q->perturb_period) {
+		q->perturb_timer.expires = jiffies + q->perturb_period;
+		add_timer(&q->perturb_timer);
+	}
+
+	return 0;
+}
+
+static int esfq_change(struct Qdisc *sch, struct nlattr *opt)
+{
+	struct esfq_sched_data *q = qdisc_priv(sch);
+	struct esfq_sched_data new;
+	struct sk_buff *skb;
+	int err;
+
+	/* set up new queue */
+	memset(&new, 0, sizeof(struct esfq_sched_data));
+	new.quantum = psched_mtu(qdisc_dev(sch)); /* default */
+	if ((err = esfq_q_init(&new, opt)))
+		return err;
+
+	/* copy all packets from the old queue to the new queue */
+	sch_tree_lock(sch);
+	while ((skb = esfq_q_dequeue(q)) != NULL)
+		esfq_q_enqueue(skb, &new, ESFQ_TAIL);
+
+	/* clean up the old queue */
+	esfq_q_destroy(q);
+
+	/* copy elements of the new queue into the old queue */
+	q->perturb_period = new.perturb_period;
+	q->quantum        = new.quantum;
+	q->limit          = new.limit;
+	q->depth          = new.depth;
+	q->hash_divisor   = new.hash_divisor;
+	q->hash_kind      = new.hash_kind;
+	q->tail           = new.tail;
+	q->max_depth      = new.max_depth;
+	q->ht    = new.ht;
+	q->dep   = new.dep;
+	q->next  = new.next;
+	q->allot = new.allot;
+	q->hash  = new.hash;
+	q->qs    = new.qs;
+
+	/* finish up */
+	if (q->perturb_period) {
+		q->perturb_timer.expires = jiffies + q->perturb_period;
+		add_timer(&q->perturb_timer);
+	} else {
+		q->perturbation = 0;
+	}
+	sch_tree_unlock(sch);
+	return 0;
+}
+
+static int esfq_dump(struct Qdisc *sch, struct sk_buff *skb)
+{
+	struct esfq_sched_data *q = qdisc_priv(sch);
+	unsigned char *b = skb_tail_pointer(skb);
+	struct tc_esfq_qopt opt;
+
+	opt.quantum = q->quantum;
+	opt.perturb_period = q->perturb_period/HZ;
+
+	opt.limit = q->limit;
+	opt.divisor = q->hash_divisor;
+	opt.flows = q->depth;
+	opt.hash_kind = q->hash_kind;
+
+	NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
+
+	return skb->len;
+
+nla_put_failure:
+	nlmsg_trim(skb, b);
+	return -1;
+}
+
+static struct Qdisc_ops esfq_qdisc_ops =
+{
+	.next		=	NULL,
+	.cl_ops		=	NULL,
+	.id		=	"esfq",
+	.priv_size	=	sizeof(struct esfq_sched_data),
+	.enqueue	=	esfq_enqueue,
+	.dequeue	=	esfq_dequeue,
+	.peek		=	esfq_peek,
+	.drop		=	esfq_drop,
+	.init		=	esfq_init,
+	.reset		=	esfq_reset,
+	.destroy	=	esfq_destroy,
+	.change		=	esfq_change,
+	.dump		=	esfq_dump,
+	.owner		=	THIS_MODULE,
+};
+
+static int __init esfq_module_init(void)
+{
+	return register_qdisc(&esfq_qdisc_ops);
+}
+static void __exit esfq_module_exit(void)
+{
+	unregister_qdisc(&esfq_qdisc_ops);
+}
+module_init(esfq_module_init)
+module_exit(esfq_module_exit)
+MODULE_LICENSE("GPL");
diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c
new file mode 100644
index 0000000..9fc1c62
--- /dev/null
+++ b/net/sched/sch_fq_codel.c
@@ -0,0 +1,626 @@
+/*
+ * Fair Queue CoDel discipline
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ *
+ *  Copyright (C) 2012 Eric Dumazet <edumazet@google.com>
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/jiffies.h>
+#include <linux/string.h>
+#include <linux/in.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/skbuff.h>
+#include <linux/jhash.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <net/netlink.h>
+#include <net/pkt_sched.h>
+#include <net/flow_keys.h>
+#include <net/codel.h>
+
+/*	Fair Queue CoDel.
+ *
+ * Principles :
+ * Packets are classified (internal classifier or external) on flows.
+ * This is a Stochastic model (as we use a hash, several flows
+ *			       might be hashed on same slot)
+ * Each flow has a CoDel managed queue.
+ * Flows are linked onto two (Round Robin) lists,
+ * so that new flows have priority on old ones.
+ *
+ * For a given flow, packets are not reordered (CoDel uses a FIFO)
+ * head drops only.
+ * ECN capability is on by default.
+ * Low memory footprint (64 bytes per flow)
+ */
+
+struct fq_codel_flow {
+	struct sk_buff	  *head;
+	struct sk_buff	  *tail;
+	struct list_head  flowchain;
+	int		  deficit;
+	u32		  dropped; /* number of drops (or ECN marks) on this flow */
+	struct codel_vars cvars;
+}; /* please try to keep this structure <= 64 bytes */
+
+struct fq_codel_sched_data {
+	struct tcf_proto *filter_list;	/* optional external classifier */
+	struct fq_codel_flow *flows;	/* Flows table [flows_cnt] */
+	u32		*backlogs;	/* backlog table [flows_cnt] */
+	u32		flows_cnt;	/* number of flows */
+	u32		perturbation;	/* hash perturbation */
+	u32		quantum;	/* psched_mtu(qdisc_dev(sch)); */
+	struct codel_params cparams;
+	struct codel_stats cstats;
+	u32		drop_overlimit;
+	u32		new_flow_count;
+
+	struct list_head new_flows;	/* list of new flows */
+	struct list_head old_flows;	/* list of old flows */
+};
+
+static unsigned int fq_codel_hash(const struct fq_codel_sched_data *q,
+				  const struct sk_buff *skb)
+{
+	struct flow_keys keys;
+	unsigned int hash;
+
+	skb_flow_dissect(skb, &keys);
+	hash = jhash_3words((__force u32)keys.dst,
+			    (__force u32)keys.src ^ keys.ip_proto,
+			    (__force u32)keys.ports, q->perturbation);
+	return ((u64)hash * q->flows_cnt) >> 32;
+}
+
+static unsigned int fq_codel_classify(struct sk_buff *skb, struct Qdisc *sch,
+				      int *qerr)
+{
+	struct fq_codel_sched_data *q = qdisc_priv(sch);
+	struct tcf_result res;
+	int result;
+
+	if (TC_H_MAJ(skb->priority) == sch->handle &&
+	    TC_H_MIN(skb->priority) > 0 &&
+	    TC_H_MIN(skb->priority) <= q->flows_cnt)
+		return TC_H_MIN(skb->priority);
+
+	if (!q->filter_list)
+		return fq_codel_hash(q, skb) + 1;
+
+	*qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
+	result = tc_classify(skb, q->filter_list, &res);
+	if (result >= 0) {
+#ifdef CONFIG_NET_CLS_ACT
+		switch (result) {
+		case TC_ACT_STOLEN:
+		case TC_ACT_QUEUED:
+			*qerr = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN;
+		case TC_ACT_SHOT:
+			return 0;
+		}
+#endif
+		if (TC_H_MIN(res.classid) <= q->flows_cnt)
+			return TC_H_MIN(res.classid);
+	}
+	return 0;
+}
+
+/* helper functions : might be changed when/if skb use a standard list_head */
+
+/* remove one skb from head of slot queue */
+static inline struct sk_buff *dequeue_head(struct fq_codel_flow *flow)
+{
+	struct sk_buff *skb = flow->head;
+
+	flow->head = skb->next;
+	skb->next = NULL;
+	return skb;
+}
+
+/* add skb to flow queue (tail add) */
+static inline void flow_queue_add(struct fq_codel_flow *flow,
+				  struct sk_buff *skb)
+{
+	if (flow->head == NULL)
+		flow->head = skb;
+	else
+		flow->tail->next = skb;
+	flow->tail = skb;
+	skb->next = NULL;
+}
+
+static unsigned int fq_codel_drop(struct Qdisc *sch)
+{
+	struct fq_codel_sched_data *q = qdisc_priv(sch);
+	struct sk_buff *skb;
+	unsigned int maxbacklog = 0, idx = 0, i, len;
+	struct fq_codel_flow *flow;
+
+	/* Queue is full! Find the fat flow and drop packet from it.
+	 * This might sound expensive, but with 1024 flows, we scan
+	 * 4KB of memory, and we dont need to handle a complex tree
+	 * in fast path (packet queue/enqueue) with many cache misses.
+	 */
+	for (i = 0; i < q->flows_cnt; i++) {
+		if (q->backlogs[i] > maxbacklog) {
+			maxbacklog = q->backlogs[i];
+			idx = i;
+		}
+	}
+	flow = &q->flows[idx];
+	skb = dequeue_head(flow);
+	len = qdisc_pkt_len(skb);
+	q->backlogs[idx] -= len;
+	kfree_skb(skb);
+	sch->q.qlen--;
+	sch->qstats.drops++;
+	sch->qstats.backlog -= len;
+	flow->dropped++;
+	return idx;
+}
+
+static int fq_codel_enqueue(struct sk_buff *skb, struct Qdisc *sch)
+{
+	struct fq_codel_sched_data *q = qdisc_priv(sch);
+	unsigned int idx;
+	struct fq_codel_flow *flow;
+	int uninitialized_var(ret);
+
+	idx = fq_codel_classify(skb, sch, &ret);
+	if (idx == 0) {
+		if (ret & __NET_XMIT_BYPASS)
+			sch->qstats.drops++;
+		kfree_skb(skb);
+		return ret;
+	}
+	idx--;
+
+	codel_set_enqueue_time(skb);
+	flow = &q->flows[idx];
+	flow_queue_add(flow, skb);
+	q->backlogs[idx] += qdisc_pkt_len(skb);
+	sch->qstats.backlog += qdisc_pkt_len(skb);
+
+	if (list_empty(&flow->flowchain)) {
+		list_add_tail(&flow->flowchain, &q->new_flows);
+		codel_vars_init(&flow->cvars);
+		q->new_flow_count++;
+		flow->deficit = q->quantum;
+		flow->dropped = 0;
+	}
+	if (++sch->q.qlen < sch->limit)
+		return NET_XMIT_SUCCESS;
+
+	q->drop_overlimit++;
+	/* Return Congestion Notification only if we dropped a packet
+	 * from this flow.
+	 */
+	if (fq_codel_drop(sch) == idx)
+		return NET_XMIT_CN;
+
+	/* As we dropped a packet, better let upper stack know this */
+	qdisc_tree_decrease_qlen(sch, 1);
+	return NET_XMIT_SUCCESS;
+}
+
+/* This is the specific function called from codel_dequeue()
+ * to dequeue a packet from queue. Note: backlog is handled in
+ * codel, we dont need to reduce it here.
+ */
+static struct sk_buff *dequeue(struct codel_vars *vars, struct Qdisc *sch)
+{
+	struct fq_codel_sched_data *q = qdisc_priv(sch);
+	struct fq_codel_flow *flow;
+	struct sk_buff *skb = NULL;
+
+	flow = container_of(vars, struct fq_codel_flow, cvars);
+	if (flow->head) {
+		skb = dequeue_head(flow);
+		q->backlogs[flow - q->flows] -= qdisc_pkt_len(skb);
+		sch->q.qlen--;
+	}
+	return skb;
+}
+
+static struct sk_buff *fq_codel_dequeue(struct Qdisc *sch)
+{
+	struct fq_codel_sched_data *q = qdisc_priv(sch);
+	struct sk_buff *skb;
+	struct fq_codel_flow *flow;
+	struct list_head *head;
+	u32 prev_drop_count, prev_ecn_mark;
+
+begin:
+	head = &q->new_flows;
+	if (list_empty(head)) {
+		head = &q->old_flows;
+		if (list_empty(head))
+			return NULL;
+	}
+	flow = list_first_entry(head, struct fq_codel_flow, flowchain);
+
+	if (flow->deficit <= 0) {
+		flow->deficit += q->quantum;
+		list_move_tail(&flow->flowchain, &q->old_flows);
+		goto begin;
+	}
+
+	prev_drop_count = q->cstats.drop_count;
+	prev_ecn_mark = q->cstats.ecn_mark;
+
+	skb = codel_dequeue(sch, &q->cparams, &flow->cvars, &q->cstats,
+			    dequeue);
+
+	flow->dropped += q->cstats.drop_count - prev_drop_count;
+	flow->dropped += q->cstats.ecn_mark - prev_ecn_mark;
+
+	if (!skb) {
+		/* force a pass through old_flows to prevent starvation */
+		if ((head == &q->new_flows) && !list_empty(&q->old_flows))
+			list_move_tail(&flow->flowchain, &q->old_flows);
+		else
+			list_del_init(&flow->flowchain);
+		goto begin;
+	}
+	qdisc_bstats_update(sch, skb);
+	flow->deficit -= qdisc_pkt_len(skb);
+	/* We cant call qdisc_tree_decrease_qlen() if our qlen is 0,
+	 * or HTB crashes. Defer it for next round.
+	 */
+	if (q->cstats.drop_count && sch->q.qlen) {
+		qdisc_tree_decrease_qlen(sch, q->cstats.drop_count);
+		q->cstats.drop_count = 0;
+	}
+	return skb;
+}
+
+static void fq_codel_reset(struct Qdisc *sch)
+{
+	struct sk_buff *skb;
+
+	while ((skb = fq_codel_dequeue(sch)) != NULL)
+		kfree_skb(skb);
+}
+
+static const struct nla_policy fq_codel_policy[TCA_FQ_CODEL_MAX + 1] = {
+	[TCA_FQ_CODEL_TARGET]	= { .type = NLA_U32 },
+	[TCA_FQ_CODEL_LIMIT]	= { .type = NLA_U32 },
+	[TCA_FQ_CODEL_INTERVAL]	= { .type = NLA_U32 },
+	[TCA_FQ_CODEL_ECN]	= { .type = NLA_U32 },
+	[TCA_FQ_CODEL_FLOWS]	= { .type = NLA_U32 },
+	[TCA_FQ_CODEL_QUANTUM]	= { .type = NLA_U32 },
+};
+
+static int fq_codel_change(struct Qdisc *sch, struct nlattr *opt)
+{
+	struct fq_codel_sched_data *q = qdisc_priv(sch);
+	struct nlattr *tb[TCA_FQ_CODEL_MAX + 1];
+	int err;
+
+	if (!opt)
+		return -EINVAL;
+
+	err = nla_parse_nested(tb, TCA_FQ_CODEL_MAX, opt, fq_codel_policy);
+	if (err < 0)
+		return err;
+	if (tb[TCA_FQ_CODEL_FLOWS]) {
+		if (q->flows)
+			return -EINVAL;
+		q->flows_cnt = nla_get_u32(tb[TCA_FQ_CODEL_FLOWS]);
+		if (!q->flows_cnt ||
+		    q->flows_cnt > 65536)
+			return -EINVAL;
+	}
+	sch_tree_lock(sch);
+
+	if (tb[TCA_FQ_CODEL_TARGET]) {
+		u64 target = nla_get_u32(tb[TCA_FQ_CODEL_TARGET]);
+
+		q->cparams.target = (target * NSEC_PER_USEC) >> CODEL_SHIFT;
+	}
+
+	if (tb[TCA_FQ_CODEL_INTERVAL]) {
+		u64 interval = nla_get_u32(tb[TCA_FQ_CODEL_INTERVAL]);
+
+		q->cparams.interval = (interval * NSEC_PER_USEC) >> CODEL_SHIFT;
+	}
+
+	if (tb[TCA_FQ_CODEL_LIMIT])
+		sch->limit = nla_get_u32(tb[TCA_FQ_CODEL_LIMIT]);
+
+	if (tb[TCA_FQ_CODEL_ECN])
+		q->cparams.ecn = !!nla_get_u32(tb[TCA_FQ_CODEL_ECN]);
+
+	if (tb[TCA_FQ_CODEL_QUANTUM])
+		q->quantum = max(256U, nla_get_u32(tb[TCA_FQ_CODEL_QUANTUM]));
+
+	while (sch->q.qlen > sch->limit) {
+		struct sk_buff *skb = fq_codel_dequeue(sch);
+
+		kfree_skb(skb);
+		q->cstats.drop_count++;
+	}
+	qdisc_tree_decrease_qlen(sch, q->cstats.drop_count);
+	q->cstats.drop_count = 0;
+
+	sch_tree_unlock(sch);
+	return 0;
+}
+
+static void *fq_codel_zalloc(size_t sz)
+{
+	void *ptr = kzalloc(sz, GFP_KERNEL | __GFP_NOWARN);
+
+	if (!ptr)
+		ptr = vzalloc(sz);
+	return ptr;
+}
+
+static void fq_codel_free(void *addr)
+{
+	if (addr) {
+		if (is_vmalloc_addr(addr))
+			vfree(addr);
+		else
+			kfree(addr);
+	}
+}
+
+static void fq_codel_destroy(struct Qdisc *sch)
+{
+	struct fq_codel_sched_data *q = qdisc_priv(sch);
+
+	tcf_destroy_chain(&q->filter_list);
+	fq_codel_free(q->backlogs);
+	fq_codel_free(q->flows);
+}
+
+static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt)
+{
+	struct fq_codel_sched_data *q = qdisc_priv(sch);
+	int i;
+
+	sch->limit = 10*1024;
+	q->flows_cnt = 1024;
+	q->quantum = psched_mtu(qdisc_dev(sch));
+	q->perturbation = net_random();
+	INIT_LIST_HEAD(&q->new_flows);
+	INIT_LIST_HEAD(&q->old_flows);
+	codel_params_init(&q->cparams);
+	codel_stats_init(&q->cstats);
+	q->cparams.ecn = true;
+
+	if (opt) {
+		int err = fq_codel_change(sch, opt);
+		if (err)
+			return err;
+	}
+
+	if (!q->flows) {
+		q->flows = fq_codel_zalloc(q->flows_cnt *
+					   sizeof(struct fq_codel_flow));
+		if (!q->flows)
+			return -ENOMEM;
+		q->backlogs = fq_codel_zalloc(q->flows_cnt * sizeof(u32));
+		if (!q->backlogs) {
+			fq_codel_free(q->flows);
+			return -ENOMEM;
+		}
+		for (i = 0; i < q->flows_cnt; i++) {
+			struct fq_codel_flow *flow = q->flows + i;
+
+			INIT_LIST_HEAD(&flow->flowchain);
+		}
+	}
+	if (sch->limit >= 1)
+		sch->flags |= TCQ_F_CAN_BYPASS;
+	else
+		sch->flags &= ~TCQ_F_CAN_BYPASS;
+	return 0;
+}
+
+static int fq_codel_dump(struct Qdisc *sch, struct sk_buff *skb)
+{
+	struct fq_codel_sched_data *q = qdisc_priv(sch);
+	struct nlattr *opts;
+
+	opts = nla_nest_start(skb, TCA_OPTIONS);
+	if (opts == NULL)
+		goto nla_put_failure;
+
+	if (nla_put_u32(skb, TCA_FQ_CODEL_TARGET,
+			codel_time_to_us(q->cparams.target)) ||
+	    nla_put_u32(skb, TCA_FQ_CODEL_LIMIT,
+			sch->limit) ||
+	    nla_put_u32(skb, TCA_FQ_CODEL_INTERVAL,
+			codel_time_to_us(q->cparams.interval)) ||
+	    nla_put_u32(skb, TCA_FQ_CODEL_ECN,
+			q->cparams.ecn) ||
+	    nla_put_u32(skb, TCA_FQ_CODEL_QUANTUM,
+			q->quantum) ||
+	    nla_put_u32(skb, TCA_FQ_CODEL_FLOWS,
+			q->flows_cnt))
+		goto nla_put_failure;
+
+	nla_nest_end(skb, opts);
+	return skb->len;
+
+nla_put_failure:
+	return -1;
+}
+
+static int fq_codel_dump_stats(struct Qdisc *sch, struct gnet_dump *d)
+{
+	struct fq_codel_sched_data *q = qdisc_priv(sch);
+	struct tc_fq_codel_xstats st = {
+		.type				= TCA_FQ_CODEL_XSTATS_QDISC,
+	};
+	struct list_head *pos;
+
+	st.qdisc_stats.maxpacket = q->cstats.maxpacket;
+	st.qdisc_stats.drop_overlimit = q->drop_overlimit;
+	st.qdisc_stats.ecn_mark = q->cstats.ecn_mark;
+	st.qdisc_stats.new_flow_count = q->new_flow_count;
+
+	list_for_each(pos, &q->new_flows)
+		st.qdisc_stats.new_flows_len++;
+
+	list_for_each(pos, &q->old_flows)
+		st.qdisc_stats.old_flows_len++;
+
+	return gnet_stats_copy_app(d, &st, sizeof(st));
+}
+
+static struct Qdisc *fq_codel_leaf(struct Qdisc *sch, unsigned long arg)
+{
+	return NULL;
+}
+
+static unsigned long fq_codel_get(struct Qdisc *sch, u32 classid)
+{
+	return 0;
+}
+
+static unsigned long fq_codel_bind(struct Qdisc *sch, unsigned long parent,
+			      u32 classid)
+{
+	/* we cannot bypass queue discipline anymore */
+	sch->flags &= ~TCQ_F_CAN_BYPASS;
+	return 0;
+}
+
+static void fq_codel_put(struct Qdisc *q, unsigned long cl)
+{
+}
+
+static struct tcf_proto **fq_codel_find_tcf(struct Qdisc *sch, unsigned long cl)
+{
+	struct fq_codel_sched_data *q = qdisc_priv(sch);
+
+	if (cl)
+		return NULL;
+	return &q->filter_list;
+}
+
+static int fq_codel_dump_class(struct Qdisc *sch, unsigned long cl,
+			  struct sk_buff *skb, struct tcmsg *tcm)
+{
+	tcm->tcm_handle |= TC_H_MIN(cl);
+	return 0;
+}
+
+static int fq_codel_dump_class_stats(struct Qdisc *sch, unsigned long cl,
+				     struct gnet_dump *d)
+{
+	struct fq_codel_sched_data *q = qdisc_priv(sch);
+	u32 idx = cl - 1;
+	struct gnet_stats_queue qs = { 0 };
+	struct tc_fq_codel_xstats xstats;
+
+	if (idx < q->flows_cnt) {
+		const struct fq_codel_flow *flow = &q->flows[idx];
+		const struct sk_buff *skb = flow->head;
+
+		memset(&xstats, 0, sizeof(xstats));
+		xstats.type = TCA_FQ_CODEL_XSTATS_CLASS;
+		xstats.class_stats.deficit = flow->deficit;
+		xstats.class_stats.ldelay =
+			codel_time_to_us(flow->cvars.ldelay);
+		xstats.class_stats.count = flow->cvars.count;
+		xstats.class_stats.lastcount = flow->cvars.lastcount;
+		xstats.class_stats.dropping = flow->cvars.dropping;
+		if (flow->cvars.dropping) {
+			codel_tdiff_t delta = flow->cvars.drop_next -
+					      codel_get_time();
+
+			xstats.class_stats.drop_next = (delta >= 0) ?
+				codel_time_to_us(delta) :
+				-codel_time_to_us(-delta);
+		}
+		while (skb) {
+			qs.qlen++;
+			skb = skb->next;
+		}
+		qs.backlog = q->backlogs[idx];
+		qs.drops = flow->dropped;
+	}
+	if (gnet_stats_copy_queue(d, &qs) < 0)
+		return -1;
+	if (idx < q->flows_cnt)
+		return gnet_stats_copy_app(d, &xstats, sizeof(xstats));
+	return 0;
+}
+
+static void fq_codel_walk(struct Qdisc *sch, struct qdisc_walker *arg)
+{
+	struct fq_codel_sched_data *q = qdisc_priv(sch);
+	unsigned int i;
+
+	if (arg->stop)
+		return;
+
+	for (i = 0; i < q->flows_cnt; i++) {
+		if (list_empty(&q->flows[i].flowchain) ||
+		    arg->count < arg->skip) {
+			arg->count++;
+			continue;
+		}
+		if (arg->fn(sch, i + 1, arg) < 0) {
+			arg->stop = 1;
+			break;
+		}
+		arg->count++;
+	}
+}
+
+static const struct Qdisc_class_ops fq_codel_class_ops = {
+	.leaf		=	fq_codel_leaf,
+	.get		=	fq_codel_get,
+	.put		=	fq_codel_put,
+	.tcf_chain	=	fq_codel_find_tcf,
+	.bind_tcf	=	fq_codel_bind,
+	.unbind_tcf	=	fq_codel_put,
+	.dump		=	fq_codel_dump_class,
+	.dump_stats	=	fq_codel_dump_class_stats,
+	.walk		=	fq_codel_walk,
+};
+
+static struct Qdisc_ops fq_codel_qdisc_ops __read_mostly = {
+	.cl_ops		=	&fq_codel_class_ops,
+	.id		=	"fq_codel",
+	.priv_size	=	sizeof(struct fq_codel_sched_data),
+	.enqueue	=	fq_codel_enqueue,
+	.dequeue	=	fq_codel_dequeue,
+	.peek		=	qdisc_peek_dequeued,
+	.drop		=	fq_codel_drop,
+	.init		=	fq_codel_init,
+	.reset		=	fq_codel_reset,
+	.destroy	=	fq_codel_destroy,
+	.change		=	fq_codel_change,
+	.dump		=	fq_codel_dump,
+	.dump_stats =	fq_codel_dump_stats,
+	.owner		=	THIS_MODULE,
+};
+
+static int __init fq_codel_module_init(void)
+{
+	return register_qdisc(&fq_codel_qdisc_ops);
+}
+
+static void __exit fq_codel_module_exit(void)
+{
+	unregister_qdisc(&fq_codel_qdisc_ops);
+}
+
+module_init(fq_codel_module_init)
+module_exit(fq_codel_module_exit)
+MODULE_AUTHOR("Eric Dumazet");
+MODULE_LICENSE("GPL");
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
index 9bdca2e..38461b6 100644
--- a/net/sched/sch_hfsc.c
+++ b/net/sched/sch_hfsc.c
@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2013 The Linux Foundation. All rights reserved.
  * Copyright (c) 2003 Patrick McHardy, <kaber@trash.net>
  *
  * This program is free software; you can redistribute it and/or
@@ -975,6 +976,7 @@
 	struct nlattr *opt = tca[TCA_OPTIONS];
 	struct nlattr *tb[TCA_HFSC_MAX + 1];
 	struct tc_service_curve *rsc = NULL, *fsc = NULL, *usc = NULL;
+	bool prev_rsc = false, prev_fsc = false;
 	u64 cur_time;
 	int err;
 
@@ -985,23 +987,14 @@
 	if (err < 0)
 		return err;
 
-	if (tb[TCA_HFSC_RSC]) {
+	if (tb[TCA_HFSC_RSC])
 		rsc = nla_data(tb[TCA_HFSC_RSC]);
-		if (rsc->m1 == 0 && rsc->m2 == 0)
-			rsc = NULL;
-	}
 
-	if (tb[TCA_HFSC_FSC]) {
+	if (tb[TCA_HFSC_FSC])
 		fsc = nla_data(tb[TCA_HFSC_FSC]);
-		if (fsc->m1 == 0 && fsc->m2 == 0)
-			fsc = NULL;
-	}
 
-	if (tb[TCA_HFSC_USC]) {
+	if (tb[TCA_HFSC_USC])
 		usc = nla_data(tb[TCA_HFSC_USC]);
-		if (usc->m1 == 0 && usc->m2 == 0)
-			usc = NULL;
-	}
 
 	if (cl != NULL) {
 		if (parentid) {
@@ -1022,24 +1015,70 @@
 		}
 
 		sch_tree_lock(sch);
-		if (rsc != NULL)
-			hfsc_change_rsc(cl, rsc, cur_time);
-		if (fsc != NULL)
-			hfsc_change_fsc(cl, fsc);
-		if (usc != NULL)
-			hfsc_change_usc(cl, usc, cur_time);
+		/* Changed class: if any new curves are zero, and that curve
+		   exists for this class, remove the curve. */
+		prev_rsc = cl->cl_flags & HFSC_RSC;
+		if (rsc != NULL) {
+			if (rsc->m1 == 0 && rsc->m2 == 0) {
+				if (prev_rsc) {
+					cl->cl_flags &= ~HFSC_RSC;
+					if (cl->qdisc->q.qlen != 0)
+						eltree_remove(cl);
+				}
+			} else {
+				hfsc_change_rsc(cl, rsc, cur_time);
+			}
+		}
+
+		prev_fsc = cl->cl_flags & HFSC_FSC;
+		if (fsc != NULL) {
+			if (fsc->m1 == 0 && fsc->m2 == 0) {
+				if (prev_fsc) {
+					cl->cl_flags &= ~HFSC_FSC;
+					if (cl->qdisc->q.qlen != 0) {
+						vttree_remove(cl);
+						cftree_remove(cl);
+					}
+				}
+			} else
+				hfsc_change_fsc(cl, fsc);
+		}
+
+		if (usc != NULL) {
+			if (usc->m1 == 0 && usc->m2 == 0)
+				cl->cl_flags &= ~HFSC_USC;
+			else
+				hfsc_change_usc(cl, usc, cur_time);
+		}
 
 		if (cl->qdisc->q.qlen != 0) {
-			if (cl->cl_flags & HFSC_RSC)
-				update_ed(cl, qdisc_peek_len(cl->qdisc));
-			if (cl->cl_flags & HFSC_FSC)
-				update_vf(cl, 0, cur_time);
+			unsigned int len = qdisc_peek_len(cl->qdisc);
+			if (cl->cl_flags & HFSC_RSC) {
+				if (prev_rsc)
+					update_ed(cl, len);
+				else
+					init_ed(cl, len);
+			}
+			if (cl->cl_flags & HFSC_FSC) {
+				if (prev_fsc)
+					update_vf(cl, 0, cur_time);
+				else
+					init_vf(cl, len);
+			}
 		}
 		sch_tree_unlock(sch);
 
 		return 0;
 	}
 
+	/* New class: if any curves are zero, do not create them */
+	if (rsc && (rsc->m1 == 0 && rsc->m2 == 0))
+		rsc = NULL;
+	if (fsc && (fsc->m1 == 0 && fsc->m2 == 0))
+		fsc = NULL;
+	if (usc && (usc->m1 == 0 && usc->m2 == 0))
+		usc = NULL;
+
 	if (parentid == TC_H_ROOT)
 		return -EEXIST;
 
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig
index 2e4444f..6755bce 100644
--- a/net/wireless/Kconfig
+++ b/net/wireless/Kconfig
@@ -1,5 +1,5 @@
 config WIRELESS_EXT
-	bool
+	bool "Wireless extensions"
 
 config WEXT_CORE
 	def_bool y
@@ -11,10 +11,10 @@
 	depends on WEXT_CORE
 
 config WEXT_SPY
-	bool
+	bool "WEXT_SPY"
 
 config WEXT_PRIV
-	bool
+	bool "WEXT_PRIV"
 
 config CFG80211
 	tristate "cfg80211 - wireless configuration API"
@@ -143,13 +143,13 @@
 	  you want this built into your kernel.
 
 config LIB80211_CRYPT_WEP
-	tristate
+	tristate "LIB80211_CRYPT_WEP"
 
 config LIB80211_CRYPT_CCMP
-	tristate
+	tristate "LIB80211_CRYPT_CCMP"
 
 config LIB80211_CRYPT_TKIP
-	tristate
+	tristate "LIB80211_CRYPT_TKIP"
 
 config LIB80211_DEBUG
 	bool "lib80211 debugging messages"
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 00c368c..9281e0d 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -296,7 +296,7 @@
 
 quiet_cmd_lzma = LZMA    $@
 cmd_lzma = (cat $(filter-out FORCE,$^) | \
-	lzma -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \
+	lzma e -d20 -lc1 -lp2 -pb2 -eos -si -so && $(call size_append, $(filter-out FORCE,$^))) > $@ || \
 	(rm -f $@ ; false)
 
 quiet_cmd_lzo = LZO     $@
diff --git a/scripts/gen_initramfs_list.sh b/scripts/gen_initramfs_list.sh
index b482f16..59ffa51 100644
--- a/scripts/gen_initramfs_list.sh
+++ b/scripts/gen_initramfs_list.sh
@@ -226,7 +226,7 @@
 output="/dev/stdout"
 output_file=""
 is_cpio_compressed=
-compr="gzip -n -9 -f"
+compr="gzip -n -9 -f -"
 
 arg="$1"
 case "$arg" in
@@ -240,9 +240,9 @@
 		output_file="$1"
 		cpio_list="$(mktemp ${TMPDIR:-/tmp}/cpiolist.XXXXXX)"
 		output=${cpio_list}
-		echo "$output_file" | grep -q "\.gz$" && compr="gzip -n -9 -f"
-		echo "$output_file" | grep -q "\.bz2$" && compr="bzip2 -9 -f"
-		echo "$output_file" | grep -q "\.lzma$" && compr="lzma -9 -f"
+		echo "$output_file" | grep -q "\.gz$" && compr="gzip -n -9 -f -"
+		echo "$output_file" | grep -q "\.bz2$" && compr="bzip2 -9 -f -"
+		echo "$output_file" | grep -q "\.lzma$" && compr="lzma e -d20 -lc1 -lp2 -pb2 -eos -si -so"
 		echo "$output_file" | grep -q "\.xz$" && \
 				compr="xz --check=crc32 --lzma2=dict=1MiB"
 		echo "$output_file" | grep -q "\.lzo$" && compr="lzop -9 -f"
@@ -303,7 +303,7 @@
 	if [ "${is_cpio_compressed}" = "compressed" ]; then
 		cat ${cpio_tfile} > ${output_file}
 	else
-		(cat ${cpio_tfile} | ${compr}  - > ${output_file}) \
+		(cat ${cpio_tfile} | ${compr} > ${output_file}) \
 		|| (rm -f ${output_file} ; false)
 	fi
 	[ -z ${cpio_file} ] && rm ${cpio_tfile}
diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
index 487ac6f..95ca1f3 100644
--- a/scripts/kallsyms.c
+++ b/scripts/kallsyms.c
@@ -22,6 +22,35 @@
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
+#ifdef __APPLE__
+/* Darwin has no memmem implementation, this one is ripped of the uClibc-0.9.28 source */
+void *memmem (const void *haystack, size_t haystack_len,
+                          const void *needle,  size_t needle_len)
+{
+  const char *begin;
+  const char *const last_possible
+    = (const char *) haystack + haystack_len - needle_len;
+
+  if (needle_len == 0)
+    /* The first occurrence of the empty string is deemed to occur at
+       the beginning of the string.  */
+    return (void *) haystack;
+
+  /* Sanity check, otherwise the loop might search through the whole
+     memory.  */
+  if (__builtin_expect (haystack_len < needle_len, 0))
+    return NULL;
+
+  for (begin = (const char *) haystack; begin <= last_possible; ++begin)
+    if (begin[0] == ((const char *) needle)[0] &&
+        !memcmp ((const void *) &begin[1],
+                 (const void *) ((const char *) needle + 1),
+                 needle_len - 1))
+      return (void *) begin;
+
+  return NULL;
+}
+#endif
 
 #ifndef ARRAY_SIZE
 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
index 7966265..d35bf09 100644
--- a/scripts/kconfig/Makefile
+++ b/scripts/kconfig/Makefile
@@ -123,6 +123,9 @@
 # we really need to do so. (Do not call gcc as part of make mrproper)
 HOST_EXTRACFLAGS += $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags) \
                     -DLOCALE
+ifeq ($(shell uname -s),Darwin)
+HOST_LOADLIBES  += -lncurses
+endif
 
 # ===========================================================================
 # Shared Makefile for the various kconfig executables:
diff --git a/scripts/mod/mk_elfconfig.c b/scripts/mod/mk_elfconfig.c
index 639bca7..d20b17e 100644
--- a/scripts/mod/mk_elfconfig.c
+++ b/scripts/mod/mk_elfconfig.c
@@ -1,7 +1,11 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#ifndef __APPLE__
 #include <elf.h>
+#else
+#include "../../../../../tools/sstrip/include/elf.h"
+#endif
 
 int
 main(int argc, char **argv)
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
index 51207e4..9c67fb3 100644
--- a/scripts/mod/modpost.h
+++ b/scripts/mod/modpost.h
@@ -7,7 +7,11 @@
 #include <sys/mman.h>
 #include <fcntl.h>
 #include <unistd.h>
+#if !(defined(__APPLE__) || defined(__CYGWIN__))
 #include <elf.h>
+#else
+#include "../../../../../tools/sstrip/include/elf.h"
+#endif
 
 #include "elfconfig.h"
 
diff --git a/scripts/setlocalversion b/scripts/setlocalversion
index 4d40384..ebdad63 100755
--- a/scripts/setlocalversion
+++ b/scripts/setlocalversion
@@ -168,7 +168,7 @@
 	# annotated or signed tagged state (as git describe only
 	# looks at signed or annotated tags - git tag -a/-s) and
 	# LOCALVERSION= is not specified
-	if test "${LOCALVERSION+set}" != "set"; then
+	if test "${CONFIG_LOCALVERSION+set}" != "set"; then
 		scm=$(scm_version --short)
 		res="$res${scm:++}"
 	fi
diff --git a/sound/core/Kconfig b/sound/core/Kconfig
index b413ed0..0fd99a0 100644
--- a/sound/core/Kconfig
+++ b/sound/core/Kconfig
@@ -7,7 +7,7 @@
 	select SND_TIMER
 
 config SND_HWDEP
-	tristate
+	tristate "Sound hardware support"
 
 config SND_RAWMIDI
 	tristate
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c
index 372b0b8..da5767c 100644
--- a/sound/soc/codecs/tlv320aic32x4.c
+++ b/sound/soc/codecs/tlv320aic32x4.c
@@ -1,6 +1,7 @@
 /*
  * linux/sound/soc/codecs/tlv320aic32x4.c
  *
+ * Copyright (c) 2013 The Linux Foundation. All rights reserved.
  * Copyright 2011 Vista Silicon S.L.
  *
  * Author: Javier Martin <javier.martin@vista-silicon.com>
@@ -29,6 +30,7 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
+#include <linux/spi/spi.h>
 #include <linux/cdev.h>
 #include <linux/slab.h>
 
@@ -62,6 +64,7 @@
 	u32 sysclk;
 	u8 page_no;
 	void *control_data;
+	enum snd_soc_control_type control_type;
 	u32 power_cfg;
 	u32 micpga_routing;
 	bool swapdacs;
@@ -120,29 +123,43 @@
 
 static const struct aic32x4_rate_divs aic32x4_divs[] = {
 	/* 8k rate */
+	{AIC32X4_FREQ_11289600, 8000, 1, 10, 0000, 504, 14, 2, 126, 14, 8, 24},
 	{AIC32X4_FREQ_12000000, 8000, 1, 7, 6800, 768, 5, 3, 128, 5, 18, 24},
+	{AIC32X4_FREQ_12288000, 8000, 1, 8, 0000, 768, 8, 2, 128, 8, 12, 24},
 	{AIC32X4_FREQ_24000000, 8000, 2, 7, 6800, 768, 15, 1, 64, 45, 4, 24},
 	{AIC32X4_FREQ_25000000, 8000, 2, 7, 3728, 768, 15, 1, 64, 45, 4, 24},
 	/* 11.025k rate */
+	{AIC32X4_FREQ_11289600, 11025, 1, 8, 0000, 512, 16, 1, 128, 16, 4, 16},
 	{AIC32X4_FREQ_12000000, 11025, 1, 7, 5264, 512, 8, 2, 128, 8, 8, 16},
+	{AIC32X4_FREQ_12288000, 11025, 1, 11, 0250, 512, 12, 2, 128, 12, 8, 16},
 	{AIC32X4_FREQ_24000000, 11025, 2, 7, 5264, 512, 16, 1, 64, 32, 4, 16},
 	/* 16k rate */
+	{AIC32X4_FREQ_11289600, 16000, 1, 10, 0000, 252, 14, 2, 126, 14, 4, 12},
 	{AIC32X4_FREQ_12000000, 16000, 1, 7, 6800, 384, 5, 3, 128, 5, 9, 12},
+	{AIC32X4_FREQ_12288000, 16000, 1, 8, 0000, 384, 8, 2, 128, 8, 6, 12},
 	{AIC32X4_FREQ_24000000, 16000, 2, 7, 6800, 384, 15, 1, 64, 18, 5, 12},
 	{AIC32X4_FREQ_25000000, 16000, 2, 7, 3728, 384, 15, 1, 64, 18, 5, 12},
 	/* 22.05k rate */
+	{AIC32X4_FREQ_11289600, 22050, 1, 8, 0000, 256, 8, 2, 128, 8, 4, 8},
 	{AIC32X4_FREQ_12000000, 22050, 1, 7, 5264, 256, 4, 4, 128, 4, 8, 8},
+	{AIC32X4_FREQ_12288000, 22050, 1, 11, 0250, 256, 12, 2, 128, 12, 4, 8},
 	{AIC32X4_FREQ_24000000, 22050, 2, 7, 5264, 256, 16, 1, 64, 16, 4, 8},
 	{AIC32X4_FREQ_25000000, 22050, 2, 7, 2253, 256, 16, 1, 64, 16, 4, 8},
 	/* 32k rate */
+	{AIC32X4_FREQ_11289600, 32000, 1, 10, 0000, 126, 7, 4, 63, 7, 8, 6},
 	{AIC32X4_FREQ_12000000, 32000, 1, 7, 1680, 192, 2, 7, 64, 2, 21, 6},
+	{AIC32X4_FREQ_12288000, 32000, 1, 8, 0000, 192, 8, 2, 64, 8, 6, 6},
 	{AIC32X4_FREQ_24000000, 32000, 2, 7, 1680, 192, 7, 2, 64, 7, 6, 6},
 	/* 44.1k rate */
+	{AIC32X4_FREQ_11289600, 44100, 1, 8, 0000, 128, 8, 2, 64, 8, 4, 4},
 	{AIC32X4_FREQ_12000000, 44100, 1, 7, 5264, 128, 2, 8, 128, 2, 8, 4},
+	{AIC32X4_FREQ_12288000, 44100, 1, 11, 0250, 128, 12, 2, 128, 12, 2, 4},
 	{AIC32X4_FREQ_24000000, 44100, 2, 7, 5264, 128, 8, 2, 64, 8, 4, 4},
 	{AIC32X4_FREQ_25000000, 44100, 2, 7, 2253, 128, 8, 2, 64, 8, 4, 4},
 	/* 48k rate */
+	{AIC32X4_FREQ_11289600, 48000, 1, 10, 0000, 84, 7, 4, 42, 7, 8, 4},
 	{AIC32X4_FREQ_12000000, 48000, 1, 8, 1920, 128, 2, 8, 128, 2, 8, 4},
+	{AIC32X4_FREQ_12288000, 48000, 1, 8, 0000, 128, 8, 2, 128, 8, 2, 4},
 	{AIC32X4_FREQ_24000000, 48000, 2, 8, 1920, 128, 8, 2, 64, 8, 4, 4},
 	{AIC32X4_FREQ_25000000, 48000, 2, 7, 8643, 128, 8, 2, 64, 8, 4, 4}
 };
@@ -271,11 +288,20 @@
 	data[1] = new_page & 0xff;
 
 	ret = codec->hw_write(codec->control_data, data, 2);
-	if (ret == 2) {
-		aic32x4->page_no = new_page;
-		return 0;
+	if (aic32x4->control_type == SND_SOC_SPI) {
+		if (ret == 0) {
+			aic32x4->page_no = new_page;
+			return 0;
+		} else {
+			return ret;
+		}
 	} else {
-		return ret;
+		if (ret == 2) {
+			aic32x4->page_no = new_page;
+			return 0;
+		} else {
+			return ret;
+		}
 	}
 }
 
@@ -298,7 +324,10 @@
 			return ret;
 	}
 
-	data[0] = fixed_reg & 0xff;
+	if (aic32x4->control_type == SND_SOC_SPI)
+		data[0] = (fixed_reg << 1);
+	else
+		data[0] = fixed_reg & 0xff;
 	data[1] = val & 0xff;
 
 	if (codec->hw_write(codec->control_data, data, 2) == 2)
@@ -313,13 +342,24 @@
 	unsigned int page = reg / 128;
 	unsigned int fixed_reg = reg % 128;
 	int ret;
+	u8 buffer;
 
 	if (aic32x4->page_no != page) {
 		ret = aic32x4_change_page(codec, page);
 		if (ret != 0)
 			return ret;
 	}
-	return i2c_smbus_read_byte_data(codec->control_data, fixed_reg & 0xff);
+
+	if (aic32x4->control_type == SND_SOC_SPI) {
+		buffer = (fixed_reg<<1) | 0x01;
+		ret = spi_write_then_read(codec->control_data, &buffer, 1, &buffer, 1);
+		if (ret) {
+			dev_err(codec->dev, "AIC32x4 reg read error\n");
+			return -EIO;
+		}
+		return (unsigned int)buffer;
+	} else
+		return i2c_smbus_read_byte_data(codec->control_data, fixed_reg & 0xff);
 }
 
 static inline int aic32x4_get_divs(int mclk, int rate)
@@ -355,7 +395,9 @@
 	struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
 
 	switch (freq) {
+	case AIC32X4_FREQ_11289600:
 	case AIC32X4_FREQ_12000000:
+	case AIC32X4_FREQ_12288000:
 	case AIC32X4_FREQ_24000000:
 	case AIC32X4_FREQ_25000000:
 		aic32x4->sysclk = freq;
@@ -547,6 +589,7 @@
 		/* Switch on BCLK_N Divider */
 		snd_soc_update_bits(codec, AIC32X4_BCLKN,
 				    AIC32X4_BCLKEN, AIC32X4_BCLKEN);
+
 		break;
 	case SND_SOC_BIAS_PREPARE:
 		break;
@@ -628,7 +671,10 @@
 	struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
 	u32 tmp_reg;
 
-	codec->hw_write = (hw_write_t) i2c_master_send;
+	if (aic32x4->control_type == SND_SOC_SPI)
+		codec->hw_write = (hw_write_t) spi_write;
+	else
+		codec->hw_write = (hw_write_t) i2c_master_send;
 	codec->control_data = aic32x4->control_data;
 
 	snd_soc_write(codec, AIC32X4_RESET, 0x01);
@@ -641,11 +687,9 @@
 	if (aic32x4->power_cfg & AIC32X4_PWR_AVDD_DVDD_WEAK_DISABLE) {
 		snd_soc_write(codec, AIC32X4_PWRCFG, AIC32X4_AVDDWEAKDISABLE);
 	}
-
 	tmp_reg = (aic32x4->power_cfg & AIC32X4_PWR_AIC32X4_LDO_ENABLE) ?
 			AIC32X4_LDOCTLEN : 0;
 	snd_soc_write(codec, AIC32X4_LDOCTL, tmp_reg);
-
 	tmp_reg = snd_soc_read(codec, AIC32X4_CMMODE);
 	if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_LDOIN_RANGE_18_36) {
 		tmp_reg |= AIC32X4_LDOIN_18_36;
@@ -694,6 +738,7 @@
 	.set_bias_level = aic32x4_set_bias_level,
 };
 
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 static __devinit int aic32x4_i2c_probe(struct i2c_client *i2c,
 				      const struct i2c_device_id *id)
 {
@@ -707,6 +752,7 @@
 		return -ENOMEM;
 
 	aic32x4->control_data = i2c;
+	aic32x4->control_type = SND_SOC_I2C;
 	i2c_set_clientdata(i2c, aic32x4);
 
 	if (pdata) {
@@ -745,23 +791,91 @@
 	.remove =   __devexit_p(aic32x4_i2c_remove),
 	.id_table = aic32x4_i2c_id,
 };
+#endif
+
+#if defined(CONFIG_SPI_MASTER)
+static int __devinit aic32x4_spi_probe(struct spi_device *spi)
+{
+	struct aic32x4_pdata *pdata = spi->dev.platform_data;
+	struct aic32x4_priv *aic32x4;
+	int ret;
+
+	aic32x4 = devm_kzalloc(&spi->dev, sizeof(struct aic32x4_priv),
+			       GFP_KERNEL);
+	if (aic32x4 == NULL)
+		return -ENOMEM;
+
+	spi->mode = SPI_MODE_1;
+	ret = spi_setup(spi);
+	if (ret < 0)
+		return ret;
+
+	aic32x4->control_data = spi;
+	aic32x4->control_type = SND_SOC_SPI;
+	spi_set_drvdata(spi, aic32x4);
+
+	if (pdata) {
+		aic32x4->power_cfg = pdata->power_cfg;
+		aic32x4->swapdacs = pdata->swapdacs;
+		aic32x4->micpga_routing = pdata->micpga_routing;
+	} else {
+		aic32x4->power_cfg = 0;
+		aic32x4->swapdacs = false;
+		aic32x4->micpga_routing = 0;
+	}
+
+	ret = snd_soc_register_codec(&spi->dev,
+			&soc_codec_dev_aic32x4, &aic32x4_dai, 1);
+	return ret;
+}
+
+static int __devexit aic32x4_spi_remove(struct spi_device *spi)
+{
+	snd_soc_unregister_codec(&spi->dev);
+	return 0;
+}
+
+static struct spi_driver aic32x4_spi_driver = {
+	.driver = {
+		.name	= "tlv320aic32x4-spi",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= aic32x4_spi_probe,
+	.remove		= __devexit_p(aic32x4_spi_remove),
+};
+#endif /* CONFIG_SPI_MASTER */
+
 
 static int __init aic32x4_modinit(void)
 {
 	int ret = 0;
 
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 	ret = i2c_add_driver(&aic32x4_i2c_driver);
 	if (ret != 0) {
 		printk(KERN_ERR "Failed to register aic32x4 I2C driver: %d\n",
 		       ret);
 	}
+#endif
+#if defined(CONFIG_SPI_MASTER)
+	ret = spi_register_driver(&aic32x4_spi_driver);
+	if (ret != 0) {
+		printk(KERN_ERR "Failed to register aic32x4 SPI driver: %d\n",
+		       ret);
+	}
+#endif
 	return ret;
 }
 module_init(aic32x4_modinit);
 
 static void __exit aic32x4_exit(void)
 {
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
 	i2c_del_driver(&aic32x4_i2c_driver);
+#endif
+#if defined(CONFIG_SPI_MASTER)
+	spi_unregister_driver(&aic32x4_spi_driver);
+#endif
 }
 module_exit(aic32x4_exit);
 
diff --git a/sound/soc/codecs/tlv320aic32x4.h b/sound/soc/codecs/tlv320aic32x4.h
index aae2b24..4ae0072 100644
--- a/sound/soc/codecs/tlv320aic32x4.h
+++ b/sound/soc/codecs/tlv320aic32x4.h
@@ -1,6 +1,8 @@
 /*
  * tlv320aic32x4.h
  *
+ * Copyright (c) 2013 The Linux Foundation. All rights reserved.
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
@@ -85,7 +87,9 @@
 #define AIC32X4_LMICPGAVOL	(AIC32X4_PAGE1 + 59)
 #define AIC32X4_RMICPGAVOL	(AIC32X4_PAGE1 + 60)
 
+#define AIC32X4_FREQ_11289600 11289600
 #define AIC32X4_FREQ_12000000 12000000
+#define AIC32X4_FREQ_12288000 12288000
 #define AIC32X4_FREQ_24000000 24000000
 #define AIC32X4_FREQ_25000000 25000000