linux-2.6.24: hipox machine support patch rebased to linux-2.6.24.7
authorSteffen Sledz <sledz@dresearch.de>
Fri, 15 Jan 2010 07:22:12 +0000 (08:22 +0100)
committerSteffen Sledz <sledz@dresearch.de>
Fri, 15 Jan 2010 07:26:26 +0000 (08:26 +0100)
Signed-off-by: Steffen Sledz <sledz@dresearch.de>
recipes/linux/linux-2.6.24/hipox/hipox.patch

index e2d8575..cd944e7 100644 (file)
@@ -1,268 +1,6 @@
-diff -Nurd linux-2.6.24/.gitignore linux-2.6.24-oxe810/.gitignore
---- linux-2.6.24/.gitignore    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/.gitignore     1970-01-01 01:00:00.000000000 +0100
-@@ -1,54 +0,0 @@
--#
--# NOTE! Don't add files that are generated in specific
--# subdirectories here. Add them in the ".gitignore" file
--# in that subdirectory instead.
--#
--# Normal rules
--#
--.*
--*.o
--*.o.*
--*.a
--*.s
--*.ko
--*.so
--*.so.dbg
--*.mod.c
--*.i
--*.lst
--*.symtypes
--
--#
--# Top-level generic files
--#
--tags
--TAGS
--vmlinux*
--!vmlinux.lds.S
--System.map
--Module.symvers
--!.gitignore
--
--#
--# Generated include files
--#
--include/asm
--include/asm-*/asm-offsets.h
--include/config
--include/linux/autoconf.h
--include/linux/compile.h
--include/linux/version.h
--include/linux/utsrelease.h
--
--# stgit generated dirs
--patches-*
--
--# quilt's files
--patches
--series
--
--# cscope files
--cscope.*
--
--*.orig
--*.rej
-diff -Nurd linux-2.6.24/.mailmap linux-2.6.24-oxe810/.mailmap
---- linux-2.6.24/.mailmap      2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/.mailmap       1970-01-01 01:00:00.000000000 +0100
-@@ -1,98 +0,0 @@
--#
--# This list is used by git-shortlog to fix a few botched name translations
--# in the git archive, either because the author's full name was messed up
--# and/or not always written the same way, making contributions from the
--# same person appearing not to be so or badly displayed.
--#
--# repo-abbrev: /pub/scm/linux/kernel/git/
--#
--
--Aaron Durbin <adurbin@google.com>
--Adam Oldham <oldhamca@gmail.com>
--Adam Radford <aradford@gmail.com>
--Adrian Bunk <bunk@stusta.de>
--Alan Cox <alan@lxorguk.ukuu.org.uk>
--Alan Cox <root@hraefn.swansea.linux.org.uk>
--Aleksey Gorelov <aleksey_gorelov@phoenix.com>
--Al Viro <viro@ftp.linux.org.uk>
--Al Viro <viro@zenIV.linux.org.uk>
--Andreas Herrmann <aherrman@de.ibm.com>
--Andrew Morton <akpm@osdl.org>
--Andrew Vasquez <andrew.vasquez@qlogic.com>
--Andy Adamson <andros@citi.umich.edu>
--Arnaud Patard <arnaud.patard@rtp-net.org>
--Arnd Bergmann <arnd@arndb.de>
--Axel Dyks <xl@xlsigned.net>
--Ben Gardner <bgardner@wabtec.com>
--Ben M Cahill <ben.m.cahill@intel.com>
--Björn Steinbrink <B.Steinbrink@gmx.de>
--Brian Avery <b.avery@hp.com>
--Brian King <brking@us.ibm.com>
--Christoph Hellwig <hch@lst.de>
--Corey Minyard <minyard@acm.org>
--David Brownell <david-b@pacbell.net>
--David Woodhouse <dwmw2@shinybook.infradead.org>
--Domen Puncer <domen@coderock.org>
--Douglas Gilbert <dougg@torque.net>
--Ed L. Cashin <ecashin@coraid.com>
--Evgeniy Polyakov <johnpol@2ka.mipt.ru>
--Felipe W Damasio <felipewd@terra.com.br>
--Felix Kuhling <fxkuehl@gmx.de>
--Felix Moeller <felix@derklecks.de>
--Filipe Lautert <filipe@icewall.org>
--Franck Bui-Huu <vagabon.xyz@gmail.com>
--Frank Zago <fzago@systemfabricworks.com>
--Greg Kroah-Hartman <greg@echidna.(none)>
--Greg Kroah-Hartman <gregkh@suse.de>
--Greg Kroah-Hartman <greg@kroah.com>
--Henk Vergonet <Henk.Vergonet@gmail.com>
--Henrik Kretzschmar <henne@nachtwindheim.de>
--Herbert Xu <herbert@gondor.apana.org.au>
--Jacob Shin <Jacob.Shin@amd.com>
--James Bottomley <jejb@mulgrave.(none)>
--James Bottomley <jejb@titanic.il.steeleye.com>
--James E Wilson <wilson@specifix.com>
--James Ketrenos <jketreno@io.(none)>
--Jean Tourrilhes <jt@hpl.hp.com>
--Jeff Garzik <jgarzik@pretzel.yyz.us>
--Jens Axboe <axboe@suse.de>
--Jens Osterkamp <Jens.Osterkamp@de.ibm.com>
--John Stultz <johnstul@us.ibm.com>
--Juha Yrjola <at solidboot.com>
--Juha Yrjola <juha.yrjola@nokia.com>
--Juha Yrjola <juha.yrjola@solidboot.com>
--Kay Sievers <kay.sievers@vrfy.org>
--Kenneth W Chen <kenneth.w.chen@intel.com>
--Koushik <raghavendra.koushik@neterion.com>
--Leonid I Ananiev <leonid.i.ananiev@intel.com>
--Linas Vepstas <linas@austin.ibm.com>
--Matthieu CASTET <castet.matthieu@free.fr>
--Michael Buesch <mb@bu3sch.de>
--Michael Buesch <mbuesch@freenet.de>
--Michel Dänzer <michel@tungstengraphics.com>
--Mitesh shah <mshah@teja.com>
--Morten Welinder <terra@gnome.org>
--Morten Welinder <welinder@anemone.rentec.com>
--Morten Welinder <welinder@darter.rentec.com>
--Morten Welinder <welinder@troll.com>
--Nguyen Anh Quynh <aquynh@gmail.com>
--Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
--Patrick Mochel <mochel@digitalimplant.org>
--Peter A Jonsson <pj@ludd.ltu.se>
--Praveen BP <praveenbp@ti.com>
--Rajesh Shah <rajesh.shah@intel.com>
--Ralf Baechle <ralf@linux-mips.org>
--Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
--Rémi Denis-Courmont <rdenis@simphalempin.com>
--Rudolf Marek <R.Marek@sh.cvut.cz>
--Rui Saraiva <rmps@joel.ist.utl.pt>
--Sachin P Sant <ssant@in.ibm.com>
--Sam Ravnborg <sam@mars.ravnborg.org>
--Simon Kelley <simon@thekelleys.org.uk>
--Stéphane Witzmann <stephane.witzmann@ubpmes.univ-bpclermont.fr>
--Stephen Hemminger <shemminger@osdl.org>
--Tejun Heo <htejun@gmail.com>
--Thomas Graf <tgraf@suug.ch>
--Tony Luck <tony.luck@intel.com>
--Tsuneo Yoshioka <Tsuneo.Yoshioka@f-secure.com>
--Valdis Kletnieks <Valdis.Kletnieks@vt.edu>
-diff -Nurd linux-2.6.24/Documentation/video4linux/CARDLIST.cx23885 linux-2.6.24-oxe810/Documentation/video4linux/CARDLIST.cx23885
---- linux-2.6.24/Documentation/video4linux/CARDLIST.cx23885    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/Documentation/video4linux/CARDLIST.cx23885     2008-06-11 17:47:23.000000000 +0200
-@@ -1,5 +1,5 @@
-   0 -> UNKNOWN/GENERIC                                     [0070:3400]
-   1 -> Hauppauge WinTV-HVR1800lp                           [0070:7600]
--  2 -> Hauppauge WinTV-HVR1800                             [0070:7800,0070:7801]
-+  2 -> Hauppauge WinTV-HVR1800                             [0070:7800,0070:7801,0070:7809]
-   3 -> Hauppauge WinTV-HVR1250                             [0070:7911]
-   4 -> DViCO FusionHDTV5 Express                           [18ac:d500]
-diff -Nurd linux-2.6.24/Makefile linux-2.6.24-oxe810/Makefile
---- linux-2.6.24/Makefile      2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/Makefile       2008-06-11 17:50:34.000000000 +0200
-@@ -1,8 +1,8 @@
- VERSION = 2
- PATCHLEVEL = 6
- SUBLEVEL = 24
--EXTRAVERSION =
--NAME = Arr Matey! A Hairy Bilge Rat!
-+EXTRAVERSION = .4
-+NAME = Err Metey! A Heury Beelge-a Ret!
- # *DOCUMENTATION*
- # To see a list of typical targets execute "make help"
-@@ -190,8 +190,8 @@
- # Default value for CROSS_COMPILE is not to prefix executables
- # Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile
--ARCH          ?= $(SUBARCH)
--CROSS_COMPILE ?=
-+ARCH          ?= arm
-+CROSS_COMPILE ?= arm-linux-uclibcgnueabi-
- # Architecture as present in compile.h
- UTS_MACHINE   := $(ARCH)
-diff -Nurd linux-2.6.24/arch/arm/Kconfig linux-2.6.24-oxe810/arch/arm/Kconfig
---- linux-2.6.24/arch/arm/Kconfig      2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/Kconfig       2008-06-11 17:47:58.000000000 +0200
-@@ -409,6 +409,10 @@
-       help
-         Support for TI's OMAP platform (OMAP1 and OMAP2).
-+config ARCH_HIPOX
-+      bool "Oxford Semiconductor NAS SoC"
-+      help
-+        This enables support for Oxsemi NAS SoC
- endchoice
- source "arch/arm/mach-clps711x/Kconfig"
-@@ -461,6 +465,8 @@
- source "arch/arm/mach-versatile/Kconfig"
-+source "arch/arm/mach-hipox/Kconfig"
-+
- source "arch/arm/mach-aaec2000/Kconfig"
- source "arch/arm/mach-realview/Kconfig"
-@@ -537,7 +543,7 @@
-       bool
- config PCI
--      bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB || ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE
-+      bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB || ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE || ARCH_HIPOX
-       help
-         Find out whether you have a PCI motherboard. PCI is the name of a
-         bus system, i.e. the way the CPU talks to the other stuff inside
-@@ -653,11 +659,13 @@
-         to have accurate timekeeping with dynamic tick.
- config HZ
--      int
-+      int "Kernel timer tick rate"
-       default 128 if ARCH_L7200
-       default 200 if ARCH_EBSA110 || ARCH_S3C2410
-       default OMAP_32K_TIMER_HZ if ARCH_OMAP && OMAP_32K_TIMER
-       default 100
-+      help
-+              Sets the number of timer tick interrupts per second
- config AEABI
-       bool "Use the ARM EABI to compile the kernel"
-@@ -1010,7 +1018,7 @@
- if PCMCIA || ARCH_CLPS7500 || ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX \
-       || ARCH_L7200 || ARCH_LH7A40X || ARCH_PXA || ARCH_RPC \
-       || ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE \
--      || ARCH_IXP23XX
-+      || ARCH_IXP23XX || ARCH_HIPOX
- source "drivers/ide/Kconfig"
- endif
-diff -Nurd linux-2.6.24/arch/arm/Makefile linux-2.6.24-oxe810/arch/arm/Makefile
---- linux-2.6.24/arch/arm/Makefile     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/Makefile      2008-06-11 17:47:58.000000000 +0200
-@@ -127,6 +127,7 @@
-  machine-$(CONFIG_ARCH_VERSATILE)  := versatile
-  machine-$(CONFIG_ARCH_IMX)      := imx
-  machine-$(CONFIG_ARCH_H720X)    := h720x
-+ machine-$(CONFIG_ARCH_HIPOX)    := hipox
-  machine-$(CONFIG_ARCH_AAEC2000)   := aaec2000
-  machine-$(CONFIG_ARCH_REALVIEW)   := realview
-  machine-$(CONFIG_ARCH_AT91)     := at91
-diff -Nurd linux-2.6.24/arch/arm/configs/hipox_810_eabi_dse_defconfig linux-2.6.24-oxe810/arch/arm/configs/hipox_810_eabi_dse_defconfig
---- linux-2.6.24/arch/arm/configs/hipox_810_eabi_dse_defconfig 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/configs/hipox_810_eabi_dse_defconfig  2008-06-11 17:47:52.000000000 +0200
+diff -Nurd linux-2.6.24.4/arch/arm/configs/hipox_810_eabi_dse_defconfig linux-2.6.24/arch/arm/configs/hipox_810_eabi_dse_defconfig
+--- linux-2.6.24.4/arch/arm/configs/hipox_810_eabi_dse_defconfig       1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/configs/hipox_810_eabi_dse_defconfig 2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,1233 @@
 +#
 +# Automatically generated make config: don't edit
@@ -1497,9 +1235,9 @@ diff -Nurd linux-2.6.24/arch/arm/configs/hipox_810_eabi_dse_defconfig linux-2.6.
 +CONFIG_HAS_IOMEM=y
 +CONFIG_HAS_IOPORT=y
 +CONFIG_HAS_DMA=y
-diff -Nurd linux-2.6.24/arch/arm/configs/hipox_810_eabi_upgrade_defconfig linux-2.6.24-oxe810/arch/arm/configs/hipox_810_eabi_upgrade_defconfig
---- linux-2.6.24/arch/arm/configs/hipox_810_eabi_upgrade_defconfig     1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/configs/hipox_810_eabi_upgrade_defconfig      2008-06-11 17:47:52.000000000 +0200
+diff -Nurd linux-2.6.24.4/arch/arm/configs/hipox_810_eabi_upgrade_defconfig linux-2.6.24/arch/arm/configs/hipox_810_eabi_upgrade_defconfig
+--- linux-2.6.24.4/arch/arm/configs/hipox_810_eabi_upgrade_defconfig   1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/configs/hipox_810_eabi_upgrade_defconfig     2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,901 @@
 +#
 +# Automatically generated make config: don't edit
@@ -2402,9 +2140,9 @@ diff -Nurd linux-2.6.24/arch/arm/configs/hipox_810_eabi_upgrade_defconfig linux-
 +CONFIG_HAS_IOMEM=y
 +CONFIG_HAS_IOPORT=y
 +CONFIG_HAS_DMA=y
-diff -Nurd linux-2.6.24/arch/arm/configs/hipox_810_eabi_wd_eval_defconfig linux-2.6.24-oxe810/arch/arm/configs/hipox_810_eabi_wd_eval_defconfig
---- linux-2.6.24/arch/arm/configs/hipox_810_eabi_wd_eval_defconfig     1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/configs/hipox_810_eabi_wd_eval_defconfig      2008-06-11 17:47:52.000000000 +0200
+diff -Nurd linux-2.6.24.4/arch/arm/configs/hipox_810_eabi_wd_eval_defconfig linux-2.6.24/arch/arm/configs/hipox_810_eabi_wd_eval_defconfig
+--- linux-2.6.24.4/arch/arm/configs/hipox_810_eabi_wd_eval_defconfig   1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/configs/hipox_810_eabi_wd_eval_defconfig     2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,1096 @@
 +#
 +# Automatically generated make config: don't edit
@@ -3502,9 +3240,9 @@ diff -Nurd linux-2.6.24/arch/arm/configs/hipox_810_eabi_wd_eval_defconfig linux-
 +CONFIG_HAS_IOMEM=y
 +CONFIG_HAS_IOPORT=y
 +CONFIG_HAS_DMA=y
-diff -Nurd linux-2.6.24/arch/arm/configs/hipox_810_eabi_wd_prod_defconfig linux-2.6.24-oxe810/arch/arm/configs/hipox_810_eabi_wd_prod_defconfig
---- linux-2.6.24/arch/arm/configs/hipox_810_eabi_wd_prod_defconfig     1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/configs/hipox_810_eabi_wd_prod_defconfig      2008-06-11 17:47:52.000000000 +0200
+diff -Nurd linux-2.6.24.4/arch/arm/configs/hipox_810_eabi_wd_prod_defconfig linux-2.6.24/arch/arm/configs/hipox_810_eabi_wd_prod_defconfig
+--- linux-2.6.24.4/arch/arm/configs/hipox_810_eabi_wd_prod_defconfig   1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/configs/hipox_810_eabi_wd_prod_defconfig     2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,1108 @@
 +#
 +# Automatically generated make config: don't edit
@@ -4614,9 +4352,65 @@ diff -Nurd linux-2.6.24/arch/arm/configs/hipox_810_eabi_wd_prod_defconfig linux-
 +CONFIG_HAS_IOMEM=y
 +CONFIG_HAS_IOPORT=y
 +CONFIG_HAS_DMA=y
-diff -Nurd linux-2.6.24/arch/arm/kernel/armksyms.c linux-2.6.24-oxe810/arch/arm/kernel/armksyms.c
---- linux-2.6.24/arch/arm/kernel/armksyms.c    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/kernel/armksyms.c     2008-06-11 17:47:43.000000000 +0200
+diff -Nurd linux-2.6.24.4/arch/arm/Kconfig linux-2.6.24/arch/arm/Kconfig
+--- linux-2.6.24.4/arch/arm/Kconfig    2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/arch/arm/Kconfig      2010-01-14 14:01:15.000000000 +0100
+@@ -409,6 +409,10 @@
+       help
+         Support for TI's OMAP platform (OMAP1 and OMAP2).
++config ARCH_HIPOX
++      bool "Oxford Semiconductor NAS SoC"
++      help
++        This enables support for Oxsemi NAS SoC
+ endchoice
+ source "arch/arm/mach-clps711x/Kconfig"
+@@ -461,6 +465,8 @@
+ source "arch/arm/mach-versatile/Kconfig"
++source "arch/arm/mach-hipox/Kconfig"
++
+ source "arch/arm/mach-aaec2000/Kconfig"
+ source "arch/arm/mach-realview/Kconfig"
+@@ -537,7 +543,7 @@
+       bool
+ config PCI
+-      bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB || ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE
++      bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB || ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE || ARCH_HIPOX
+       help
+         Find out whether you have a PCI motherboard. PCI is the name of a
+         bus system, i.e. the way the CPU talks to the other stuff inside
+@@ -653,11 +659,13 @@
+         to have accurate timekeeping with dynamic tick.
+ config HZ
+-      int
++      int "Kernel timer tick rate"
+       default 128 if ARCH_L7200
+       default 200 if ARCH_EBSA110 || ARCH_S3C2410
+       default OMAP_32K_TIMER_HZ if ARCH_OMAP && OMAP_32K_TIMER
+       default 100
++      help
++              Sets the number of timer tick interrupts per second
+ config AEABI
+       bool "Use the ARM EABI to compile the kernel"
+@@ -1010,7 +1018,7 @@
+ if PCMCIA || ARCH_CLPS7500 || ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX \
+       || ARCH_L7200 || ARCH_LH7A40X || ARCH_PXA || ARCH_RPC \
+       || ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE \
+-      || ARCH_IXP23XX
++      || ARCH_IXP23XX || ARCH_HIPOX
+ source "drivers/ide/Kconfig"
+ endif
+diff -Nurd linux-2.6.24.4/arch/arm/kernel/armksyms.c linux-2.6.24/arch/arm/kernel/armksyms.c
+--- linux-2.6.24.4/arch/arm/kernel/armksyms.c  2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/arch/arm/kernel/armksyms.c    2010-01-14 14:01:15.000000000 +0100
 @@ -114,9 +114,15 @@
  EXPORT_SYMBOL(__strncpy_from_user);
  
@@ -4633,9 +4427,9 @@ diff -Nurd linux-2.6.24/arch/arm/kernel/armksyms.c linux-2.6.24-oxe810/arch/arm/
  
  EXPORT_SYMBOL(__get_user_1);
  EXPORT_SYMBOL(__get_user_2);
-diff -Nurd linux-2.6.24/arch/arm/kernel/bios32.c linux-2.6.24-oxe810/arch/arm/kernel/bios32.c
---- linux-2.6.24/arch/arm/kernel/bios32.c      2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/kernel/bios32.c       2008-06-11 17:47:43.000000000 +0200
+diff -Nurd linux-2.6.24.4/arch/arm/kernel/bios32.c linux-2.6.24/arch/arm/kernel/bios32.c
+--- linux-2.6.24.4/arch/arm/kernel/bios32.c    2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/arch/arm/kernel/bios32.c      2010-01-14 14:01:15.000000000 +0100
 @@ -616,7 +616,7 @@
        }
  }
@@ -4645,9 +4439,9 @@ diff -Nurd linux-2.6.24/arch/arm/kernel/bios32.c linux-2.6.24-oxe810/arch/arm/ke
  {
        if (!strcmp(str, "debug")) {
                debug_pci = 1;
-diff -Nurd linux-2.6.24/arch/arm/kernel/calls.S linux-2.6.24-oxe810/arch/arm/kernel/calls.S
---- linux-2.6.24/arch/arm/kernel/calls.S       2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/kernel/calls.S        2008-06-11 17:47:43.000000000 +0200
+diff -Nurd linux-2.6.24.4/arch/arm/kernel/calls.S linux-2.6.24/arch/arm/kernel/calls.S
+--- linux-2.6.24.4/arch/arm/kernel/calls.S     2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/arch/arm/kernel/calls.S       2010-01-14 14:01:15.000000000 +0100
 @@ -362,6 +362,7 @@
  /* 350 */     CALL(sys_timerfd)
                CALL(sys_eventfd)
@@ -4656,9 +4450,9 @@ diff -Nurd linux-2.6.24/arch/arm/kernel/calls.S linux-2.6.24-oxe810/arch/arm/ker
  #ifndef syscalls_counted
  .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
  #define syscalls_counted
-diff -Nurd linux-2.6.24/arch/arm/kernel/head.S linux-2.6.24-oxe810/arch/arm/kernel/head.S
---- linux-2.6.24/arch/arm/kernel/head.S        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/kernel/head.S 2008-06-11 17:47:43.000000000 +0200
+diff -Nurd linux-2.6.24.4/arch/arm/kernel/head.S linux-2.6.24/arch/arm/kernel/head.S
+--- linux-2.6.24.4/arch/arm/kernel/head.S      2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/arch/arm/kernel/head.S        2010-01-14 14:01:15.000000000 +0100
 @@ -59,6 +59,34 @@
  #define KERNEL_END    _end
  #endif
@@ -4858,9 +4652,9 @@ diff -Nurd linux-2.6.24/arch/arm/kernel/head.S linux-2.6.24-oxe810/arch/arm/kern
  
  #ifdef CONFIG_DEBUG_LL
        ldr     r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags
-diff -Nurd linux-2.6.24/arch/arm/kernel/process.c linux-2.6.24-oxe810/arch/arm/kernel/process.c
---- linux-2.6.24/arch/arm/kernel/process.c     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/kernel/process.c      2008-06-11 17:47:43.000000000 +0200
+diff -Nurd linux-2.6.24.4/arch/arm/kernel/process.c linux-2.6.24/arch/arm/kernel/process.c
+--- linux-2.6.24.4/arch/arm/kernel/process.c   2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/arch/arm/kernel/process.c     2010-01-14 14:01:15.000000000 +0100
 @@ -117,7 +117,7 @@
  void (*pm_idle)(void);
  EXPORT_SYMBOL(pm_idle);
@@ -4870,9 +4664,9 @@ diff -Nurd linux-2.6.24/arch/arm/kernel/process.c linux-2.6.24-oxe810/arch/arm/k
  EXPORT_SYMBOL(pm_power_off);
  
  void (*arm_pm_restart)(char str) = arm_machine_restart;
-diff -Nurd linux-2.6.24/arch/arm/kernel/vmlinux.lds.S linux-2.6.24-oxe810/arch/arm/kernel/vmlinux.lds.S
---- linux-2.6.24/arch/arm/kernel/vmlinux.lds.S 2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/kernel/vmlinux.lds.S  2008-06-11 17:47:43.000000000 +0200
+diff -Nurd linux-2.6.24.4/arch/arm/kernel/vmlinux.lds.S linux-2.6.24/arch/arm/kernel/vmlinux.lds.S
+--- linux-2.6.24.4/arch/arm/kernel/vmlinux.lds.S       2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/arch/arm/kernel/vmlinux.lds.S 2010-01-14 14:01:15.000000000 +0100
 @@ -86,8 +86,659 @@
  #endif
        }
@@ -5535,23 +5329,9 @@ diff -Nurd linux-2.6.24/arch/arm/kernel/vmlinux.lds.S linux-2.6.24-oxe810/arch/a
                        __exception_text_start = .;
                        *(.exception.text)
                        __exception_text_end = .;
-diff -Nurd linux-2.6.24/arch/arm/lib/Makefile linux-2.6.24-oxe810/arch/arm/lib/Makefile
---- linux-2.6.24/arch/arm/lib/Makefile 2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/lib/Makefile  2008-06-11 17:47:47.000000000 +0200
-@@ -29,6 +29,10 @@
- endif
- endif
-+ifeq ($(CONFIG_HIPOX_DMA_COPIES),y)
-+  lib-y       += hipox_copies.o
-+endif
-+
- lib-$(CONFIG_MMU) += $(mmu-y)
- ifeq ($(CONFIG_CPU_32v3),y)
-diff -Nurd linux-2.6.24/arch/arm/lib/clear_user.S linux-2.6.24-oxe810/arch/arm/lib/clear_user.S
---- linux-2.6.24/arch/arm/lib/clear_user.S     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/lib/clear_user.S      2008-06-11 17:47:47.000000000 +0200
+diff -Nurd linux-2.6.24.4/arch/arm/lib/clear_user.S linux-2.6.24/arch/arm/lib/clear_user.S
+--- linux-2.6.24.4/arch/arm/lib/clear_user.S   2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/arch/arm/lib/clear_user.S     2010-01-14 14:01:15.000000000 +0100
 @@ -18,7 +18,11 @@
   *          : sz   - number of bytes to clear
   * Returns  : number of bytes NOT cleared
@@ -5564,9 +5344,9 @@ diff -Nurd linux-2.6.24/arch/arm/lib/clear_user.S linux-2.6.24-oxe810/arch/arm/l
                stmfd   sp!, {r1, lr}
                mov     r2, #0
                cmp     r1, #4
-diff -Nurd linux-2.6.24/arch/arm/lib/copy_from_user.S linux-2.6.24-oxe810/arch/arm/lib/copy_from_user.S
---- linux-2.6.24/arch/arm/lib/copy_from_user.S 2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/lib/copy_from_user.S  2008-06-11 17:47:47.000000000 +0200
+diff -Nurd linux-2.6.24.4/arch/arm/lib/copy_from_user.S linux-2.6.24/arch/arm/lib/copy_from_user.S
+--- linux-2.6.24.4/arch/arm/lib/copy_from_user.S       2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/arch/arm/lib/copy_from_user.S 2010-01-14 14:01:15.000000000 +0100
 @@ -83,7 +83,12 @@
  
        .text
@@ -5580,9 +5360,9 @@ diff -Nurd linux-2.6.24/arch/arm/lib/copy_from_user.S linux-2.6.24-oxe810/arch/a
  
  #include "copy_template.S"
  
-diff -Nurd linux-2.6.24/arch/arm/lib/copy_to_user.S linux-2.6.24-oxe810/arch/arm/lib/copy_to_user.S
---- linux-2.6.24/arch/arm/lib/copy_to_user.S   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/lib/copy_to_user.S    2008-06-11 17:47:47.000000000 +0200
+diff -Nurd linux-2.6.24.4/arch/arm/lib/copy_to_user.S linux-2.6.24/arch/arm/lib/copy_to_user.S
+--- linux-2.6.24.4/arch/arm/lib/copy_to_user.S 2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/arch/arm/lib/copy_to_user.S   2010-01-14 14:01:15.000000000 +0100
 @@ -86,7 +86,12 @@
  
        .text
@@ -5596,31 +5376,9 @@ diff -Nurd linux-2.6.24/arch/arm/lib/copy_to_user.S linux-2.6.24-oxe810/arch/arm
  
  #include "copy_template.S"
  
-diff -Nurd linux-2.6.24/arch/arm/lib/memcpy.S linux-2.6.24-oxe810/arch/arm/lib/memcpy.S
---- linux-2.6.24/arch/arm/lib/memcpy.S 2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/lib/memcpy.S  2008-06-11 17:47:47.000000000 +0200
-@@ -53,6 +53,7 @@
- /* Prototype: void *memcpy(void *dest, const void *src, size_t n); */
-+.section ".text.memcpy"
- ENTRY(memcpy)
- #include "copy_template.S"
-diff -Nurd linux-2.6.24/arch/arm/lib/memzero.S linux-2.6.24-oxe810/arch/arm/lib/memzero.S
---- linux-2.6.24/arch/arm/lib/memzero.S        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/lib/memzero.S 2008-06-11 17:47:47.000000000 +0200
-@@ -30,6 +30,7 @@
-  * memzero again.
-  */
-+.section ".text.__memzero"
- ENTRY(__memzero)
-       mov     r2, #0                  @ 1
-       ands    r3, r0, #3              @ 1 unaligned?
-diff -Nurd linux-2.6.24/arch/arm/lib/hipox_copies.c linux-2.6.24-oxe810/arch/arm/lib/hipox_copies.c
---- linux-2.6.24/arch/arm/lib/hipox_copies.c   1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/lib/hipox_copies.c    2008-06-11 17:47:47.000000000 +0200
+diff -Nurd linux-2.6.24.4/arch/arm/lib/hipox_copies.c linux-2.6.24/arch/arm/lib/hipox_copies.c
+--- linux-2.6.24.4/arch/arm/lib/hipox_copies.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/lib/hipox_copies.c   2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,261 @@
 +/*
 + * linux/arch/arm/lib/nas_copies.c
@@ -5883,938 +5641,252 @@ diff -Nurd linux-2.6.24/arch/arm/lib/hipox_copies.c linux-2.6.24-oxe810/arch/arm
 +//   return count - transfered;
 +//}
 +
-diff -Nurd linux-2.6.24/arch/arm/mach-hipox/Kconfig linux-2.6.24-oxe810/arch/arm/mach-hipox/Kconfig
---- linux-2.6.24/arch/arm/mach-hipox/Kconfig   1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mach-hipox/Kconfig    2008-06-11 17:47:55.000000000 +0200
-@@ -0,0 +1,574 @@
-+if ARCH_HIPOX
+diff -Nurd linux-2.6.24.4/arch/arm/lib/Makefile linux-2.6.24/arch/arm/lib/Makefile
+--- linux-2.6.24.4/arch/arm/lib/Makefile       2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/arch/arm/lib/Makefile 2010-01-14 14:01:15.000000000 +0100
+@@ -29,6 +29,10 @@
+ endif
+ endif
++ifeq ($(CONFIG_HIPOX_DMA_COPIES),y)
++  lib-y       += hipox_copies.o
++endif
 +
-+menu "Oxford Semiconductor NAS Options"
+ lib-$(CONFIG_MMU) += $(mmu-y)
+ ifeq ($(CONFIG_CPU_32v3),y)
+diff -Nurd linux-2.6.24.4/arch/arm/lib/memcpy.S linux-2.6.24/arch/arm/lib/memcpy.S
+--- linux-2.6.24.4/arch/arm/lib/memcpy.S       2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/arch/arm/lib/memcpy.S 2010-01-14 14:01:15.000000000 +0100
+@@ -53,6 +53,7 @@
+ /* Prototype: void *memcpy(void *dest, const void *src, size_t n); */
++.section ".text.memcpy"
+ ENTRY(memcpy)
+ #include "copy_template.S"
+diff -Nurd linux-2.6.24.4/arch/arm/lib/memzero.S linux-2.6.24/arch/arm/lib/memzero.S
+--- linux-2.6.24.4/arch/arm/lib/memzero.S      2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/arch/arm/lib/memzero.S        2010-01-14 14:01:15.000000000 +0100
+@@ -30,6 +30,7 @@
+  * memzero again.
+  */
++.section ".text.__memzero"
+ ENTRY(__memzero)
+       mov     r2, #0                  @ 1
+       ands    r3, r0, #3              @ 1 unaligned?
+diff -Nurd linux-2.6.24.4/arch/arm/mach-hipox/ahb_mon.c linux-2.6.24/arch/arm/mach-hipox/ahb_mon.c
+--- linux-2.6.24.4/arch/arm/mach-hipox/ahb_mon.c       1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/mach-hipox/ahb_mon.c 2010-01-14 14:01:15.000000000 +0100
+@@ -0,0 +1,177 @@
++/*
++ *  linux/arch/arm/mach-hipox/ahb_mon.c
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
 +
-+config ARCH_HIPOX_FPGA
-+      bool "FPGA platform"
-+      default n
-+      help
-+        This enables support for Oxsemi NAS SoC FPGA development platform
++#include <linux/kernel.h>
++#include <asm/io.h>
++#include <asm/arch/hardware.h>
 +
-+config HIPOX_CORE_CLK
-+      int "Integrator core module processor clock frequency in MHz"
-+      depends on ARCH_HIPOX_FPGA
-+      default 175
-+      help
-+              Maximum reliable frequency 175MHz
++#ifdef CONFIG_HIPOX_AHB_MON
++static void start_ahb_monitors(void)
++{
++    writel(AHB_MON_MODE_ACTIVE << AHB_MON_MODE_MODE_BIT, AHB_MON_ARM_D + AHB_MON_MODE_REG_OFFSET);
++    writel(AHB_MON_MODE_ACTIVE << AHB_MON_MODE_MODE_BIT, AHB_MON_ARM_I + AHB_MON_MODE_REG_OFFSET);
++    writel(AHB_MON_MODE_ACTIVE << AHB_MON_MODE_MODE_BIT, AHB_MON_DMA_A + AHB_MON_MODE_REG_OFFSET);
++    writel(AHB_MON_MODE_ACTIVE << AHB_MON_MODE_MODE_BIT, AHB_MON_DMA_B + AHB_MON_MODE_REG_OFFSET);
++    writel(AHB_MON_MODE_ACTIVE << AHB_MON_MODE_MODE_BIT, AHB_MON_LEON  + AHB_MON_MODE_REG_OFFSET);
++    writel(AHB_MON_MODE_ACTIVE << AHB_MON_MODE_MODE_BIT, AHB_MON_USB  + AHB_MON_MODE_REG_OFFSET);
++    writel(AHB_MON_MODE_ACTIVE << AHB_MON_MODE_MODE_BIT, AHB_MON_MAC  + AHB_MON_MODE_REG_OFFSET);
++    writel(AHB_MON_MODE_ACTIVE << AHB_MON_MODE_MODE_BIT, AHB_MON_PCI  + AHB_MON_MODE_REG_OFFSET);
++}
 +
-+config HIPOX_CORE_BUS_CLK_DIV
-+      int "Integrator core module bus clock divider"
-+      depends on ARCH_HIPOX_FPGA
-+      default 4
-+      help
-+              Must be greater than 0
++void init_ahb_monitors(
++    AHB_MON_HWRITE_T ahb_mon_hwrite,
++    unsigned hburst_mask,
++    unsigned hburst_match,
++    unsigned hprot_mask,
++    unsigned hprot_match)
++{
++    u32 hburst_mask_value  = (hburst_mask  & ((1 << AHB_MON_HBURST_MASK_NUM_BITS)  - 1));
++    u32 hburst_match_value = (hburst_match & ((1 << AHB_MON_HBURST_MATCH_NUM_BITS) - 1));
++    u32 hprot_mask_value   = (hprot_mask   & ((1 << AHB_MON_HPROT_MASK_NUM_BITS)   - 1));
++    u32 hprot_match_value  = (hprot_match  & ((1 << AHB_MON_HPROT_MATCH_NUM_BITS)  - 1));
 +
-+config NOMINAL_PLL400_FREQ
-+      int "The master clock frequency of the Soc"
-+      default 400000000
-+      help
-+              The PLL400 clock is divided by 2 to drive the ARM clock and by
-+              4 to drive the AHB clock
++    u32 hburst_reg_value = (hburst_mask_value << AHB_MON_HBURST_MASK_BIT) | (hburst_match_value << AHB_MON_HBURST_MATCH_BIT);
++    u32 hprot_reg_value  = (hprot_mask_value  << AHB_MON_HPROT_MASK_BIT)  | (hprot_match_value  << AHB_MON_HPROT_MATCH_BIT);
 +
-+config NOMINAL_RPSCLK_FREQ
-+      int "The input clock frequency to the RPS"
-+      default 25000000
-+      help
-+              The RPS clock feeds into a prescaler and from there feeds the
-+              RPS timers
++printk("$Ghburst reg value = 0x%08x\n", hburst_reg_value);
++printk("$Ghprot reg value  = 0x%08x\n", hprot_reg_value);
 +
-+choice
-+      prompt "HIPOX system type"
-+      default HIPOX_VERSION_0X800
++    // Reset all the counters and set their operating mode
++    writel(AHB_MON_MODE_RESET << AHB_MON_MODE_MODE_BIT, AHB_MON_ARM_D + AHB_MON_MODE_REG_OFFSET);
++    writel(ahb_mon_hwrite << AHB_MON_HWRITE_COUNT_BIT,  AHB_MON_ARM_D + AHB_MON_HWRITE_REG_OFFSET);
++    writel(0UL,                                         AHB_MON_ARM_D + AHB_MON_HADDR_LOW_REG_OFFSET);
++    writel(~0UL,                                        AHB_MON_ARM_D + AHB_MON_HADDR_HIGH_REG_OFFSET);
++    writel(hburst_reg_value,                            AHB_MON_ARM_D + AHB_MON_HBURST_REG_OFFSET);
++    writel(hprot_reg_value,                             AHB_MON_ARM_D + AHB_MON_HPROT_REG_OFFSET);
 +
-+config HIPOX_VERSION_0X800
-+      bool "0X800"
-+      select ARM_AMBA
-+      help
-+        Support for the 0X800 SoC
++    writel(AHB_MON_MODE_RESET << AHB_MON_MODE_MODE_BIT, AHB_MON_ARM_I + AHB_MON_MODE_REG_OFFSET);
++    writel(ahb_mon_hwrite << AHB_MON_HWRITE_COUNT_BIT,  AHB_MON_ARM_I + AHB_MON_HWRITE_REG_OFFSET);
++    writel(0UL,                                         AHB_MON_ARM_I + AHB_MON_HADDR_LOW_REG_OFFSET);
++    writel(~0UL,                                        AHB_MON_ARM_I + AHB_MON_HADDR_HIGH_REG_OFFSET);
++    writel(hburst_reg_value,                            AHB_MON_ARM_I + AHB_MON_HBURST_REG_OFFSET);
++    writel(hprot_reg_value,                             AHB_MON_ARM_I + AHB_MON_HPROT_REG_OFFSET);
 +
-+config HIPOX_VERSION_0X810
-+      bool "0X810"
-+      select ARM_AMBA
-+      help
-+        Support for the 0X810 SoC
++    writel(AHB_MON_MODE_RESET << AHB_MON_MODE_MODE_BIT, AHB_MON_DMA_A + AHB_MON_MODE_REG_OFFSET);
++    writel(ahb_mon_hwrite << AHB_MON_HWRITE_COUNT_BIT,  AHB_MON_DMA_A + AHB_MON_HWRITE_REG_OFFSET);
++    writel(0UL,                                         AHB_MON_DMA_A + AHB_MON_HADDR_LOW_REG_OFFSET);
++    writel(~0UL,                                        AHB_MON_DMA_A + AHB_MON_HADDR_HIGH_REG_OFFSET);
++    writel(hburst_reg_value,                            AHB_MON_DMA_A + AHB_MON_HBURST_REG_OFFSET);
++    writel(hprot_reg_value,                             AHB_MON_DMA_A + AHB_MON_HPROT_REG_OFFSET);
 +
-+config HIPOX_VERSION_0X850
-+      bool "0X850"
-+      help
-+        Support for the 0X850 SoC
-+endchoice
++    writel(AHB_MON_MODE_RESET << AHB_MON_MODE_MODE_BIT, AHB_MON_DMA_B + AHB_MON_MODE_REG_OFFSET);
++    writel(ahb_mon_hwrite << AHB_MON_HWRITE_COUNT_BIT,  AHB_MON_DMA_B + AHB_MON_HWRITE_REG_OFFSET);
++    writel(0UL,                                         AHB_MON_DMA_B + AHB_MON_HADDR_LOW_REG_OFFSET);
++    writel(~0UL,                                        AHB_MON_DMA_B + AHB_MON_HADDR_HIGH_REG_OFFSET);
++    writel(hburst_reg_value,                            AHB_MON_DMA_B + AHB_MON_HBURST_REG_OFFSET);
++    writel(hprot_reg_value,                             AHB_MON_DMA_B + AHB_MON_HPROT_REG_OFFSET);
 +
-+config ARCH_HIPOX_UART1
-+      bool "Support UART1"
-+      default n
-+      help
-+              This enables UART1 to be accessible to Linux.
-+              UARTs will be mapped to ttySn numbers from UART1 to UART4, only
-+              including those UARTs selected to be present
++    writel(AHB_MON_MODE_RESET << AHB_MON_MODE_MODE_BIT, AHB_MON_LEON  + AHB_MON_MODE_REG_OFFSET);
++    writel(ahb_mon_hwrite << AHB_MON_HWRITE_COUNT_BIT,  AHB_MON_LEON  + AHB_MON_HWRITE_REG_OFFSET);
++    writel(0UL,                                         AHB_MON_LEON  + AHB_MON_HADDR_LOW_REG_OFFSET);
++    writel(~0UL,                                        AHB_MON_LEON  + AHB_MON_HADDR_HIGH_REG_OFFSET);
++    writel(hburst_reg_value,                            AHB_MON_LEON  + AHB_MON_HBURST_REG_OFFSET);
++    writel(hprot_reg_value,                             AHB_MON_LEON  + AHB_MON_HPROT_REG_OFFSET);
 +
-+config ARCH_HIPOX_UART1_MODEM
-+      bool "Support UART1 modem control lines"
-+      depends on ARCH_HIPOX_UART1
-+      default n
-+      help
-+              Multiplex the modem control lines from UART1 onto external pins
++    writel(AHB_MON_MODE_RESET << AHB_MON_MODE_MODE_BIT, AHB_MON_USB   + AHB_MON_MODE_REG_OFFSET);
++    writel(ahb_mon_hwrite << AHB_MON_HWRITE_COUNT_BIT,  AHB_MON_USB   + AHB_MON_HWRITE_REG_OFFSET);
++    writel(0UL,                                         AHB_MON_USB   + AHB_MON_HADDR_LOW_REG_OFFSET);
++    writel(~0UL,                                        AHB_MON_USB   + AHB_MON_HADDR_HIGH_REG_OFFSET);
++    writel(hburst_reg_value,                            AHB_MON_USB   + AHB_MON_HBURST_REG_OFFSET);
++    writel(hprot_reg_value,                             AHB_MON_USB   + AHB_MON_HPROT_REG_OFFSET);
 +
-+config ARCH_HIPOX_UART2
-+      bool "Support UART2"
-+      default n
-+      help
-+              This enables UART2 to be accessible to Linux
-+              UARTs will be mapped to ttySn numbers from UART1 to UART4, only
-+              including those UARTs selected to be present
++    writel(AHB_MON_MODE_RESET << AHB_MON_MODE_MODE_BIT, AHB_MON_MAC   + AHB_MON_MODE_REG_OFFSET);
++    writel(ahb_mon_hwrite << AHB_MON_HWRITE_COUNT_BIT,  AHB_MON_MAC   + AHB_MON_HWRITE_REG_OFFSET);
++    writel(0UL,                                         AHB_MON_MAC   + AHB_MON_HADDR_LOW_REG_OFFSET);
++    writel(~0UL,                                        AHB_MON_MAC   + AHB_MON_HADDR_HIGH_REG_OFFSET);
++    writel(hburst_reg_value,                            AHB_MON_MAC   + AHB_MON_HBURST_REG_OFFSET);
++    writel(hprot_reg_value,                             AHB_MON_MAC   + AHB_MON_HPROT_REG_OFFSET);
 +
-+config ARCH_HIPOX_UART2_MODEM
-+      bool "Support UART2 modem control lines"
-+      depends on ARCH_HIPOX_UART2
-+      default n
-+      help
-+              Multiplex the modem control lines from UART2 onto external pins
++    writel(AHB_MON_MODE_RESET << AHB_MON_MODE_MODE_BIT, AHB_MON_PCI   + AHB_MON_MODE_REG_OFFSET);
++    writel(ahb_mon_hwrite << AHB_MON_HWRITE_COUNT_BIT,  AHB_MON_PCI   + AHB_MON_HWRITE_REG_OFFSET);
++    writel(0UL,                                         AHB_MON_PCI   + AHB_MON_HADDR_LOW_REG_OFFSET);
++    writel(~0UL,                                        AHB_MON_PCI   + AHB_MON_HADDR_HIGH_REG_OFFSET);
++    writel(hburst_reg_value,                            AHB_MON_PCI   + AHB_MON_HBURST_REG_OFFSET);
++    writel(hprot_reg_value,                             AHB_MON_PCI   + AHB_MON_HPROT_REG_OFFSET);
 +
-+config ARCH_HIPOX_UART3
-+      bool "Support UART3"
-+      default n
-+      help
-+              This enables UAR3 to be accessible to Linux
-+              UARTs will be mapped to ttySn numbers from UART1 to UART4, only
-+              including those UARTs selected to be present
++    // Start all the counters
++    start_ahb_monitors();
++}
 +
-+config ARCH_HIPOX_UART3_MODEM
-+      bool "Support UART3 modem control lines"
-+      depends on ARCH_HIPOX_UART3
-+      default n
-+      help
-+              Multiplex the modem control lines from UART3 onto external pins
++void restart_ahb_monitors(void)
++{
++    // Reset the counters
++    writel(AHB_MON_MODE_RESET << AHB_MON_MODE_MODE_BIT, AHB_MON_ARM_D + AHB_MON_MODE_REG_OFFSET);
++    writel(AHB_MON_MODE_RESET << AHB_MON_MODE_MODE_BIT, AHB_MON_ARM_I + AHB_MON_MODE_REG_OFFSET);
++    writel(AHB_MON_MODE_RESET << AHB_MON_MODE_MODE_BIT, AHB_MON_DMA_A + AHB_MON_MODE_REG_OFFSET);
++    writel(AHB_MON_MODE_RESET << AHB_MON_MODE_MODE_BIT, AHB_MON_DMA_B + AHB_MON_MODE_REG_OFFSET);
++    writel(AHB_MON_MODE_RESET << AHB_MON_MODE_MODE_BIT, AHB_MON_LEON  + AHB_MON_MODE_REG_OFFSET);
++    writel(AHB_MON_MODE_RESET << AHB_MON_MODE_MODE_BIT, AHB_MON_USB   + AHB_MON_MODE_REG_OFFSET);
++    writel(AHB_MON_MODE_RESET << AHB_MON_MODE_MODE_BIT, AHB_MON_MAC   + AHB_MON_MODE_REG_OFFSET);
++    writel(AHB_MON_MODE_RESET << AHB_MON_MODE_MODE_BIT, AHB_MON_PCI   + AHB_MON_MODE_REG_OFFSET);
 +
-+config ARCH_HIPOX_UART4
-+      bool "Support UART4"
-+      depends on !PCI
-+      default n
-+      help
-+              This enables UART4 to be accessible to Linux
-+              UARTs will be mapped to ttySn numbers from UART1 to UART4, only
-+              including those UARTs selected to be present
-+              UART4 always has its modem control lines available on external pins
-+              when selected (overlaying PCI functions)
++    // Start the counters
++    start_ahb_monitors();
++}
 +
-+config ARCH_HIPOX_PCI_REQGNT_0
-+      bool "Enable req/gnt for PCI device 0"
-+      depends on PCI
-+      default n
-+      help
++void read_ahb_monitors(void)
++{
++    // Prepare the counters for reading
++    writel(AHB_MON_MODE_IDLE << AHB_MON_MODE_MODE_BIT, AHB_MON_ARM_D + AHB_MON_MODE_REG_OFFSET);
++    writel(AHB_MON_MODE_IDLE << AHB_MON_MODE_MODE_BIT, AHB_MON_ARM_I + AHB_MON_MODE_REG_OFFSET);
++    writel(AHB_MON_MODE_IDLE << AHB_MON_MODE_MODE_BIT, AHB_MON_DMA_A + AHB_MON_MODE_REG_OFFSET);
++    writel(AHB_MON_MODE_IDLE << AHB_MON_MODE_MODE_BIT, AHB_MON_DMA_B + AHB_MON_MODE_REG_OFFSET);
++    writel(AHB_MON_MODE_IDLE << AHB_MON_MODE_MODE_BIT, AHB_MON_LEON  + AHB_MON_MODE_REG_OFFSET);
++    writel(AHB_MON_MODE_IDLE << AHB_MON_MODE_MODE_BIT, AHB_MON_USB   + AHB_MON_MODE_REG_OFFSET);
++    writel(AHB_MON_MODE_IDLE << AHB_MON_MODE_MODE_BIT, AHB_MON_MAC   + AHB_MON_MODE_REG_OFFSET);
++    writel(AHB_MON_MODE_IDLE << AHB_MON_MODE_MODE_BIT, AHB_MON_PCI   + AHB_MON_MODE_REG_OFFSET);
 +
-+config ARCH_HIPOX_PCI_REQGNT_1
-+      bool "Enable req/gnt for PCI device 1"
-+      depends on PCI
-+      default n
-+      help
++    // Read the counters
++    printk("ARM-D: B=%u, T=%u, W=%u\n", readl(AHB_MON_ARM_D + AHB_MON_CYCLES_REG_OFFSET),
++                                        readl(AHB_MON_ARM_D + AHB_MON_TRANSFERS_REG_OFFSET),
++                                        readl(AHB_MON_ARM_D + AHB_MON_WAITS_REG_OFFSET));
 +
-+config ARCH_HIPOX_PCI_REQGNT_2
-+      bool "Enable req/gnt for PCI device 2"
-+      depends on PCI
-+      default n
-+      help
++    printk("ARM-I: B=%u, T=%u, W=%u\n", readl(AHB_MON_ARM_I + AHB_MON_CYCLES_REG_OFFSET),
++                                        readl(AHB_MON_ARM_I + AHB_MON_TRANSFERS_REG_OFFSET),
++                                        readl(AHB_MON_ARM_I + AHB_MON_WAITS_REG_OFFSET));
 +
-+config ARCH_HIPOX_PCI_REQGNT_3
-+      bool "Enable req/gnt for PCI device 3"
-+      depends on PCI
-+      default n
-+      help
++    printk("DMA-A: B=%u, T=%u, W=%u\n", readl(AHB_MON_DMA_A + AHB_MON_CYCLES_REG_OFFSET),
++                                        readl(AHB_MON_DMA_A + AHB_MON_TRANSFERS_REG_OFFSET),
++                                        readl(AHB_MON_DMA_A + AHB_MON_WAITS_REG_OFFSET));
 +
-+config ARCH_HIPOX_PCI_CLKOUT_0
-+      bool "Enable PCI clock output 0"
-+      depends on PCI
-+      default n
-+      help
++    printk("DMA-B: B=%u, T=%u, W=%u\n", readl(AHB_MON_DMA_B + AHB_MON_CYCLES_REG_OFFSET),
++                                        readl(AHB_MON_DMA_B + AHB_MON_TRANSFERS_REG_OFFSET),
++                                        readl(AHB_MON_DMA_B + AHB_MON_WAITS_REG_OFFSET));
 +
-+config ARCH_HIPOX_PCI_CLKOUT_1
-+      bool "Enable PCI clock output 1"
-+      depends on PCI
-+      default n
-+      help
++    printk("LEON:  B=%u, T=%u, W=%u\n", readl(AHB_MON_LEON  + AHB_MON_CYCLES_REG_OFFSET),
++                                        readl(AHB_MON_LEON  + AHB_MON_TRANSFERS_REG_OFFSET),
++                                        readl(AHB_MON_LEON  + AHB_MON_WAITS_REG_OFFSET));
 +
-+config ARCH_HIPOX_PCI_CLKOUT_2
-+      bool "Enable PCI clock output 2"
-+      depends on PCI
-+      default n
-+      help
++    printk("USB:   B=%u, T=%u, W=%u\n", readl(AHB_MON_USB   + AHB_MON_CYCLES_REG_OFFSET),
++                                        readl(AHB_MON_USB   + AHB_MON_TRANSFERS_REG_OFFSET),
++                                        readl(AHB_MON_USB   + AHB_MON_WAITS_REG_OFFSET));
 +
-+config ARCH_HIPOX_PCI_CLKOUT_3
-+      bool "Enable PCI clock output 3"
-+      depends on PCI
-+      default n
-+      help
++    printk("MAC:   B=%u, T=%u, W=%u\n", readl(AHB_MON_MAC   + AHB_MON_CYCLES_REG_OFFSET),
++                                        readl(AHB_MON_MAC   + AHB_MON_TRANSFERS_REG_OFFSET),
++                                        readl(AHB_MON_MAC   + AHB_MON_WAITS_REG_OFFSET));
 +
-+config HIPOX_PCI_RESET
-+      bool "Allow PCI reset to be toggled after power up"
-+      depends on PCI
-+      default n
-+      help
-+              The SoC requires that the PCI bus reset be toggled after the
-+              rest of the SoC has emerged from reset
++    printk("PCI:   B=%u, T=%u, W=%u\n", readl(AHB_MON_PCI   + AHB_MON_CYCLES_REG_OFFSET),
++                                        readl(AHB_MON_PCI   + AHB_MON_TRANSFERS_REG_OFFSET),
++                                        readl(AHB_MON_PCI   + AHB_MON_WAITS_REG_OFFSET));
++}
++#endif // CONFIG_HIPOX_AHB_MON
 +
-+config HIPOX_PCI_RESET_GPIO
-+      int "GPIO line connected to PCI reset"
-+      depends on HIPOX_PCI_RESET
-+      default 12
-+      help
-+              The PCI bus requires a separate reset to be asserted after the
-+              reset of the SoC has emerged from reset. This defines the GPIO
-+              line which is connected to the PCI reset
+diff -Nurd linux-2.6.24.4/arch/arm/mach-hipox/cipher.c linux-2.6.24/arch/arm/mach-hipox/cipher.c
+--- linux-2.6.24.4/arch/arm/mach-hipox/cipher.c        1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/mach-hipox/cipher.c  2010-01-14 14:01:15.000000000 +0100
+@@ -0,0 +1,362 @@
++/* linux/arch/arm/mach-hipox/cipher.c
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
 +
-+config HIPOX_SATA_POWER_1
-+      bool "Allow control of SATA 1 disk power via GPIO"
-+      default n
-+      help
-+              Allow SATA disk 1 power to be turned off via GPIO lines
-+
-+config HIPOX_SATA_POWER_GPIO_1
-+      int "GPIO line connected to SATA power control for disk 1"
-+      depends on HIPOX_SATA_POWER_1
-+      default 15
-+      help
-+              The GPIO line that controls SATA disk 1 power
-+
-+config HIPOX_SATA_POWER_2
-+      bool "Allow control of SATA disk 2 power via GPIO"
-+      default n
-+      help
-+              Allow SATA disk 2 power to be turned off via GPIO lines
-+
-+config HIPOX_SATA_POWER_GPIO_2
-+      int "GPIO line connected to SATA power control for disk 2"
-+      depends on HIPOX_SATA_POWER_2
-+      default 18
-+      help
-+              The GPIO line that controls SATA disk 2 power
-+
-+config FORCE_MAX_ZONEORDER
-+      int "Max order of zoned buddy allocator"
-+      default 11
-+      help
-+              The value to be assigned to MAX_ORDER
-+
-+config SRAM_NUM_PAGES
-+      int "The number of SRAM memory pages present in the system"
-+      default 8
-+      help
-+              Determines the number of pages of SRAM that are assumed to exist in the
-+              system memory map
-+
-+config SUPPORT_LEON
-+      bool "Include support for Leon"
-+      default n
-+
-+config LEON_PAGES
-+      int "The number of 4K pages of SRAM to reserve for the LEON program"
-+      depends on SUPPORT_LEON
-+      default 2
-+      help
-+              Determines the number of 4K pages of SRAM that are reserved for the
-+              LEON program
-+
-+config LEON_COPRO
-+      bool "Load LEON networking acceleration program"
-+      depends on SUPPORT_LEON && HIPOX_VERSION_0X810
-+      default n
-+
-+config LEON_OFFLOAD_TX
-+      bool "Whether network Tx operations should be offloaded to the LEON"
-+      depends on LEON_COPRO
-+      default n
-+
-+config LEON_RESERVE_DMA_CHANNEL
-+      bool "Whether to reserve the last DMA channel for the CoPro's use"
-+      depends on LEON_OFFLOAD_TX
-+      default n
-+
-+config LEON_OFFLOAD_TSO
-+      bool "Whether network TSO operations should be offloaded to the LEON"
-+      depends on LEON_OFFLOAD_TX
-+      default n
-+
-+config LEON_START_EARLY
-+      bool "Load LEON early startup program"
-+      depends on SUPPORT_LEON
-+      default n
-+      help
-+              For situations where the LEON is to run some code unrelated to
-+              its normal network acceleration functions, this options causes
-+              the LEON code to be loaded and the LEON started early in the
-+              boot process
-+
-+config LEON_POWER_BUTTON_MONITOR
-+      tristate "Load LEON power button monitoring program"
-+      depends on SUPPORT_LEON
-+      default n
-+      help
-+              Support powering down the system via a GPIO button and when the
-+              system is powered down load a LEON program that will monitor the
-+              button for attempts to power the system back on
-+
-+config HIPOX_POWER_BUTTON_GPIO
-+      int "GPIO line connected to power button"
-+      depends on LEON_POWER_BUTTON_MONITOR
-+      default 33
-+      help
-+              Specifies the GPIO line to which the power button is connected
-+
-+config USER_RECOVERY_BUTTON_MONITOR
-+      tristate "Load user recovery button monitoring program"
-+      default n
-+      help
-+              Support User recovery of the system via a GPIO button. When the
-+              system is power cycled after the use of this button, the admin
-+              password and network settings are set to factory values.
-+
-+config HIPOX_USER_RECOVERY_BUTTON_GPIO
-+      int "GPIO line connected to user recovery button"
-+      depends on USER_RECOVERY_BUTTON_MONITOR
-+      default 32
-+      help
-+              Specifies the GPIO line to which the user recovery button is 
-+              connected.
-+
-+config HIPOX_DDR_MON
-+      bool "Poll the DDR core bus monitors from timer tick interrupt"
-+      default n
-+
-+config HIPOX_AHB_MON
-+      bool "Include support for AHB monitors"
-+      default n
-+
-+config HIPOX_MONITOR_SUBSAMPLE
-+      int "Jiffy subsample factor for AHB monitor sampling"
-+      depends on HIPOX_AHB_MON || HIPOX_DDR_MON
-+      default 10
-+      help
-+              The factor by which to subsample the jiffy count to produce AHB monitor
-+              sampling events
-+
-+config HIPOX_CACHE_LOCKDOWN
-+      bool "Allow locking down part of the caches"
-+      default n
-+
-+config HIPOX_CACHE_I_MASK
-+      int "Bit mask for I cache lockdown"
-+      depends on HIPOX_CACHE_LOCKDOWN
-+      default 0
-+      help
-+              Allowable values are:
-+              0 - No ways locked down
-+              1 - One way locked down
-+              3 - Two ways locked down
-+              7 - Three ways locked down
-+
-+config HIPOX_CACHE_D_MASK
-+      int "Bit mask for D cache lockdown"
-+      depends on HIPOX_CACHE_LOCKDOWN
-+      default 0
-+      help
-+              Allowable values are:
-+              0 - No ways locked down
-+              1 - One way locked down
-+              3 - Two ways locked down
-+              7 - Three ways locked down
-+
-+config DO_MEM_TEST
-+      bool "Perform memory copy throughput test during boot"
-+      default 0
-+
-+config CRYPTO_OXAESLRW
-+      tristate "LRW-AES hardware support"
-+      help
-+        Driver for controlling the Ox-Semi OX800 cipher core for LRW-AES
-+        encryption
-+
-+config DESCRIPTORS_PAGES
-+      int "The number of SRAM memory pages to reserve for DMA descriptors"
-+      default 1
-+      help
-+              Determines the number of pages of SRAM that are reserved for DMA
-+              descriptors
-+
-+config ARCH_HIPOX_NUM_GMAC_DESCRIPTORS
-+      int "The number of GMAC descriptors to allocate"
-+      default 112
-+
-+config ARCH_HIPOX_MAX_SATA_SG_ENTRIES
-+      int "The max. number of SG DMA descriptors to use in the single transfer"
-+      default 64
-+
-+config TACHO_THERM_AND_FAN
-+      tristate "Include support for the temperature sensing, and automatic fan control"
-+      default n
-+
-+config GPIO_TEST
-+      tristate "Device driver for exercising GPIO block."
-+      default n
-+      help
-+        Connect the I2C serial lines (SCLK, SCS, and SDT) together to run test
-+
-+config HIPOX_RTC
-+      tristate "Probe for m41t00 RTC"
-+      select I2C
-+      select I2C_ALGOBIT
-+      select I2C_HIPOX_BITBASH
-+      select RTC_CLASS
-+      select RTC_DRV_DS1307
-+      default n
-+      help
-+        The M41T00 RTC provides basic time save and restore.
-+        The device is probed for on the HIPOX bit-bash I2C bus.
-+
-+config I2S
-+      tristate "I2S test interface"
-+      default n
-+      help
-+        Say Y here to use i2s
-+        This support is also available as a module. If so, the module will be
-+        called i2s.
-+
-+config PCI_HIPOX_CARDBUS
-+    bool "Switches from a PCI/Mini-PCI bus to a Cardbus bus."
-+    depends on PCI && ARCH_HIPOX_FPGA
-+    ---help---
-+      This option limits scanning of the bus to omit the Via SATA interface.
-+      This makes the bus compatible with cardbus cards that expect to be the 
-+      only PCI device on the bus.
-+
-+config DPE_TEST
-+      tristate "Test the DPE core"
-+      default n
-+
-+config HIPOX_EARLY_PRINTK
-+      bool "Whether to output to printascii from printk"
-+      depends on DEBUG_LL
-+      help
-+              If both CONFIG_DEBUG_LL and this option are selected, then each printk
-+              call will duplicate the message in a call to printascii to get very
-+              early console output
-+
-+config HIPOX_INSTRUMENT_COPIES
-+      bool "Instrument copy_to_user and copy_from_user"
-+      default n
-+
-+config HIPOX_INSTRUMENT_COPIES_THRESHOLD
-+      int "The threshold above which copies will be instrumented"
-+      depends on HIPOX_INSTRUMENT_COPIES
-+      default 0
-+
-+config HIPOX_INSTRUMENT_COPIES_TIME
-+      bool "Whether to print copy timing to console"
-+      depends on HIPOX_INSTRUMENT_COPIES
-+      default n
-+
-+config HIPOX_INSTRUMENT_COPIES_GPIO
-+      bool "Whether to toggle a GPIO around copies"
-+      depends on HIPOX_INSTRUMENT_COPIES
-+      default n
-+
-+config HIPOX_DMA_COPIES
-+      bool "Whether to use DMA for larger user-kernel copies"
-+      default n
-+      
-+config HIPOX_DMA_COPY_THRESHOLD
-+      int "The threshold above which DMA will be used for copies"
-+      depends on HIPOX_DMA_COPIES
-+      default 1024
-+
-+config HIPOX_AHB_MONITOR_MODULE
-+      tristate "Creates a loadable module to control the AHB monitors"
-+      default n
-+      help
-+              This module publishes the current values of the AHB
-+              monitors in the /proc filing system.
-+              The monitors can be controlled by writing into this
-+              filing system
-+
-+config HIPOX_USB_TEST_MODES
-+      tristate "Create a loadable module to control the USB port test modes"
-+      default n
-+      help
-+              This module reports the port status and allows setting
-+              of the test mode in the port register via the /proc 
-+              filing system.
-+
-+config HIPOX_FRONT_LAMP_CONTROL
-+      tristate "Front Panel LED control system"
-+      depends on LEDS_CLASS
-+      default n
-+      help
-+              This module reports drives a number of GPIOs as PWM signals to drive
-+              front panel LEDs. The pattern displayed is dependent on system state.
-+
-+config LEDS_TRIGGER_SATA_DISK
-+      tristate "Front Panel SATA disk activity lamp control system"
-+      default n
-+      help
-+              This module reports drives the SATA disk activity lamp.
-+
-+config HIPOX_LED_TEST
-+      bool "Exercise the WD LEDs"
-+      default n
-+
-+config HIPOX_I2C_SDA
-+      int "I2C bit-bash data line"
-+      default 2
-+
-+config HIPOX_I2C_SCL
-+      int "I2C bit-bash clock line"
-+      default 3
-+
-+config        HIPOX_USB_PORTA_POWER_CONTROL
-+      bool "Support USB port A power control lines"
-+      default n
-+      help
-+              Whether to support power switch out and monitor in via GPIOs
-+              for USB port A
-+
-+config        HIPOX_USB_PORTB_POWER_CONTROL
-+      bool "Support USB port B power control lines"
-+      default n
-+      help
-+              Whether to support power switch out and monitor in via GPIOs
-+              for USB port B
-+
-+config        HIPOX_USB_PORTC_POWER_CONTROL
-+      bool "Support USB port C power control lines"
-+      default n
-+      help
-+              Whether to support power switch out and monitor in via GPIOs
-+              for USB port C
-+
-+config HIPOX_USB_OVERCURRENT_POLARITY_NEGATIVE
-+      bool "Set USB power monitor input polarity to negative"
-+      default n
-+      help
-+              n - Positive polarity
-+              y - Negative polarity
-+
-+config HIPOX_USB_POWER_SWITCH_POLARITY_NEGATIVE
-+      bool "Set USB power switch output polarity to negative"
-+      default n
-+      help
-+              n - Positive polarity
-+              y - Negative polarity
-+
-+config WDC_FAN_HIPOX800
-+      tristate "WD NetCenter/2NC Fan control driver"
-+      default n
-+      help
-+              This driver allows user-mode applications to control the cooling
-+              fan on Western Digital's NetCenter/2NC platform.
-+
-+config HIPOX_MAP_SRAM
-+      bool "Allow part of kernel to be mapped into SRAM"
-+      default n
-+
-+config HIPOX_COPY_CODE_TO_SRAM
-+      bool "Copy part of kernel to SRAM"
-+      depends on HIPOX_MAP_SRAM
-+      default n
-+
-+config HIPOX_SUID_INHERIT
-+      bool "Make SUID be inherited by subdirectories"
-+      default n
-+
-+config HIPOX_USB_HUB_SUPPORT
-+      bool "Enable support for on-board USB hub"
-+      default n
-+
-+config HIPOX_USB_CKOUT
-+      bool "Enable output of 12MHz USB clock on GPIO 10"
-+      depends on HIPOX_USB_HUB_SUPPORT
-+      default n
-+
-+config HIPOX_USB_HUB_RESET_CONTROL
-+      bool "Control the USB hub reset line"
-+      depends on HIPOX_USB_HUB_SUPPORT
-+      default n
-+
-+config HIPOX_USB_HUB_RESET_GPIO
-+      int "The GPIO connected to the USB hub reset"
-+      depends on HIPOX_USB_HUB_RESET_CONTROL
-+      default 27
-+
-+config HIPOX_USB_HUB_RESET_ACTIVE_HIGH
-+      int "Set to 1 for active high, 0 for active low reset"
-+      depends on HIPOX_USB_HUB_RESET_CONTROL
-+      default 1
-+
-+config HIPOX_USB_HUB_RESET_TOGGLE
-+      bool "Select to toggle reset, do not select to just deassert reset"
-+      depends on HIPOX_USB_HUB_RESET_CONTROL
-+      default y
-+
-+config HIPOX_USB_HUB_RESET_PERIOD_MS
-+      int "The period for which the USB hub reset should be asserted in milliseconds"
-+      depends on HIPOX_USB_HUB_RESET_TOGGLE
-+      default 100
-+
-+endmenu
-+
-+endif
-diff -Nurd linux-2.6.24/arch/arm/mach-hipox/Makefile linux-2.6.24-oxe810/arch/arm/mach-hipox/Makefile
---- linux-2.6.24/arch/arm/mach-hipox/Makefile  1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mach-hipox/Makefile   2008-06-11 17:47:55.000000000 +0200
-@@ -0,0 +1,43 @@
-+#
-+# Makefile for the linux kernel.
-+#
-+
-+# Object file lists.
-+
-+obj-y := hipox.o irq.o time.o dma.o pci.o ahb_mon.o leon.o samba_reserve.o
-+
-+obj-$(CONFIG_SYNOPSYS_GMAC) += gmac.o
-+
-+gmac-objs := gmac-napi.o gmac_ethtool.o gmac_phy.o gmac_desc.o gmac_offload.o
-+
-+obj-$(CONFIG_HIPOX_IBW) += ibw.o
-+
-+obj-$(CONFIG_TACHO_THERM_AND_FAN) += thermAndFan.o
-+
-+obj-$(CONFIG_I2S) += i2s.o
-+
-+obj-$(CONFIG_CRYPTO_OXAESLRW) += cipher.o
-+
-+obj-$(CONFIG_GPIO_TEST)       += gpioTest.o
-+
-+obj-$(CONFIG_I2S) += i2s.o
-+
-+obj-$(CONFIG_DPE_TEST) += dpe_test.o
-+
-+obj-$(CONFIG_HIPOX_AHB_MONITOR_MODULE) += hipox-ahb-monitor.o
-+
-+obj-$(CONFIG_HIPOX_USB_TEST_MODES) += usb-test-mode.o
-+
-+obj-$(CONFIG_LEON_POWER_BUTTON_MONITOR) += power_button.o
-+
-+obj-$(CONFIG_USER_RECOVERY_BUTTON_MONITOR) += user_recovery_button.o
-+
-+obj-$(CONFIG_HIPOX_FRONT_LAMP_CONTROL) += leds.o
-+
-+obj-$(CONFIG_WDC_FAN_HIPOX800) += wdc-fan.o
-+
-+obj-$(CONFIG_WDC_LEDS_HIPOX800) += wdc-leds.o
-+
-+obj-$(CONFIG_HIPOX_WD810_LEDS) += hipox-wd810-leds.o
-+
-+obj-$(CONFIG_WDC_LEDS_TRIGGER_SATA_DISK) += wdc-ledtrig-sata.o
-diff -Nurd linux-2.6.24/arch/arm/mach-hipox/Makefile.boot linux-2.6.24-oxe810/arch/arm/mach-hipox/Makefile.boot
---- linux-2.6.24/arch/arm/mach-hipox/Makefile.boot     1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mach-hipox/Makefile.boot      2008-06-11 17:47:55.000000000 +0200
-@@ -0,0 +1,3 @@
-+initrd_phys-$(CONFIG_ARCH_HIPOX)      := 0x48200000
-+params_phys-$(CONFIG_ARCH_HIPOX)      := 0x48000100
-+zreladdr-$(CONFIG_ARCH_HIPOX)         := 0x48008000
-diff -Nurd linux-2.6.24/arch/arm/mach-hipox/README linux-2.6.24-oxe810/arch/arm/mach-hipox/README
---- linux-2.6.24/arch/arm/mach-hipox/README    1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mach-hipox/README     2008-06-11 17:47:55.000000000 +0200
-@@ -0,0 +1,85 @@
-+
-+usb-test-modes 
-+
-+This is best built as a module which may be inserted into a running
-+Linux system only when needed.
-+The module can be built as part of the standard kernel module build
-+if the correct options are chosen in the config. 
-+
-+
-+How to use:
-+
-+copy the usb-test-mode.ko file somewhere convenient on the NAS and
-+insert the module into the system using
-+'modprobe usb-test-mode.ko'
-+
-+It should report successfull loading or an error message. Assuming it is
-+successful /proc will have an 'usb_test_mode' entry (verify with ls).
-+
-+Actions:
-+read the current port status:
-+cat /proc/usb_test_mode/read
-+
-+set port 1 into test mode 4:
-+echo 4 > /proc/usb_test_mode/write1
-+
-+
-+When testing is completed the module can be removed from the linux
-+system using:
-+rmmod usb_test_mode
-+
-+ahb_mon 
-+
-+This should be built as a module. 
-+
-+How to use:
-+
-+insert the module into a working system by typing 
-+'modprobe hipox-ahb-monitor'
-+
-+When successfully installed a directory  entry will appear in /proc for
-+hipox-ahb-monitor. In the directory will be a writeable file for each
-+AHB monitor and a control file. There will also be a readable file for
-+obtaining the counts stored in all the ahb monitors.
-+
-+
-+Actions:
-+set a monitor to a limited range, burst mode etc using
-+low addres, high address, mode, burst mode, burst mask, hprot, hprot mask
-+
-+Use the echo command to set data into the /proc/hipox-ahb-monitor an example is
-+the following script to observe the activities of the ARM processor on the GMAC
-+core when pinging a remote machine:
-+---------------------------
-+#!/bin/sh -x
-+#
-+
-+# start montoring of ARM data bus to MAC
-+# format is "low high mode burst mask hprot mask"
-+# mode - 1 write 2 read 3 read write.
-+
-+echo 2 > /proc/hipox-test/control
-+
-+echo 0 > /proc/hipox-test/control
-+
-+
-+echo "0x40400000,0x405fffff,3,0,0,0,0" > /proc/hipox-test/ARM_Data
-+echo "0x40400000,0x405fffff,3,0,0,0,0" > /proc/hipox-test/Arm_Inst
-+echo "0,4,3,0,0,0,0" > /proc/hipox-test/CoPro
-+echo "0,4,3,0,0,0,0" > /proc/hipox-test/DMA_A
-+echo "0,4,3,0,0,0,0" > /proc/hipox-test/DMA_B
-+echo "0,4,3,0,0,0,0" > /proc/hipox-test/GMAC
-+echo "0,4,3,0,0,0,0" > /proc/hipox-test/PCI
-+echo "0,4,3,0,0,0,0" > /proc/hipox-test/USBHS
-+
-+echo 1 > /proc/hipox-test/control
-+
-+ping -c 1 172.31.0.102
-+
-+echo 0 > /proc/hipox-test/control
-+--------------------------------------
-+
-+When testing is commplete the module can be removed using 
-+rmmod hipox-ahb-monitor
-+
-+
-Files linux-2.6.24/arch/arm/mach-hipox/ThermCalc.xls and linux-2.6.24-oxe810/arch/arm/mach-hipox/ThermCalc.xls differ
-diff -Nurd linux-2.6.24/arch/arm/mach-hipox/ahb_mon.c linux-2.6.24-oxe810/arch/arm/mach-hipox/ahb_mon.c
---- linux-2.6.24/arch/arm/mach-hipox/ahb_mon.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mach-hipox/ahb_mon.c  2008-06-11 17:47:55.000000000 +0200
-@@ -0,0 +1,177 @@
-+/*
-+ *  linux/arch/arm/mach-hipox/ahb_mon.c
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+
-+#include <linux/kernel.h>
-+#include <asm/io.h>
-+#include <asm/arch/hardware.h>
-+
-+#ifdef CONFIG_HIPOX_AHB_MON
-+static void start_ahb_monitors(void)
-+{
-+    writel(AHB_MON_MODE_ACTIVE << AHB_MON_MODE_MODE_BIT, AHB_MON_ARM_D + AHB_MON_MODE_REG_OFFSET);
-+    writel(AHB_MON_MODE_ACTIVE << AHB_MON_MODE_MODE_BIT, AHB_MON_ARM_I + AHB_MON_MODE_REG_OFFSET);
-+    writel(AHB_MON_MODE_ACTIVE << AHB_MON_MODE_MODE_BIT, AHB_MON_DMA_A + AHB_MON_MODE_REG_OFFSET);
-+    writel(AHB_MON_MODE_ACTIVE << AHB_MON_MODE_MODE_BIT, AHB_MON_DMA_B + AHB_MON_MODE_REG_OFFSET);
-+    writel(AHB_MON_MODE_ACTIVE << AHB_MON_MODE_MODE_BIT, AHB_MON_LEON  + AHB_MON_MODE_REG_OFFSET);
-+    writel(AHB_MON_MODE_ACTIVE << AHB_MON_MODE_MODE_BIT, AHB_MON_USB  + AHB_MON_MODE_REG_OFFSET);
-+    writel(AHB_MON_MODE_ACTIVE << AHB_MON_MODE_MODE_BIT, AHB_MON_MAC  + AHB_MON_MODE_REG_OFFSET);
-+    writel(AHB_MON_MODE_ACTIVE << AHB_MON_MODE_MODE_BIT, AHB_MON_PCI  + AHB_MON_MODE_REG_OFFSET);
-+}
-+
-+void init_ahb_monitors(
-+    AHB_MON_HWRITE_T ahb_mon_hwrite,
-+    unsigned hburst_mask,
-+    unsigned hburst_match,
-+    unsigned hprot_mask,
-+    unsigned hprot_match)
-+{
-+    u32 hburst_mask_value  = (hburst_mask  & ((1 << AHB_MON_HBURST_MASK_NUM_BITS)  - 1));
-+    u32 hburst_match_value = (hburst_match & ((1 << AHB_MON_HBURST_MATCH_NUM_BITS) - 1));
-+    u32 hprot_mask_value   = (hprot_mask   & ((1 << AHB_MON_HPROT_MASK_NUM_BITS)   - 1));
-+    u32 hprot_match_value  = (hprot_match  & ((1 << AHB_MON_HPROT_MATCH_NUM_BITS)  - 1));
-+
-+    u32 hburst_reg_value = (hburst_mask_value << AHB_MON_HBURST_MASK_BIT) | (hburst_match_value << AHB_MON_HBURST_MATCH_BIT);
-+    u32 hprot_reg_value  = (hprot_mask_value  << AHB_MON_HPROT_MASK_BIT)  | (hprot_match_value  << AHB_MON_HPROT_MATCH_BIT);
-+
-+printk("$Ghburst reg value = 0x%08x\n", hburst_reg_value);
-+printk("$Ghprot reg value  = 0x%08x\n", hprot_reg_value);
-+
-+    // Reset all the counters and set their operating mode
-+    writel(AHB_MON_MODE_RESET << AHB_MON_MODE_MODE_BIT, AHB_MON_ARM_D + AHB_MON_MODE_REG_OFFSET);
-+    writel(ahb_mon_hwrite << AHB_MON_HWRITE_COUNT_BIT,  AHB_MON_ARM_D + AHB_MON_HWRITE_REG_OFFSET);
-+    writel(0UL,                                         AHB_MON_ARM_D + AHB_MON_HADDR_LOW_REG_OFFSET);
-+    writel(~0UL,                                        AHB_MON_ARM_D + AHB_MON_HADDR_HIGH_REG_OFFSET);
-+    writel(hburst_reg_value,                            AHB_MON_ARM_D + AHB_MON_HBURST_REG_OFFSET);
-+    writel(hprot_reg_value,                             AHB_MON_ARM_D + AHB_MON_HPROT_REG_OFFSET);
-+
-+    writel(AHB_MON_MODE_RESET << AHB_MON_MODE_MODE_BIT, AHB_MON_ARM_I + AHB_MON_MODE_REG_OFFSET);
-+    writel(ahb_mon_hwrite << AHB_MON_HWRITE_COUNT_BIT,  AHB_MON_ARM_I + AHB_MON_HWRITE_REG_OFFSET);
-+    writel(0UL,                                         AHB_MON_ARM_I + AHB_MON_HADDR_LOW_REG_OFFSET);
-+    writel(~0UL,                                        AHB_MON_ARM_I + AHB_MON_HADDR_HIGH_REG_OFFSET);
-+    writel(hburst_reg_value,                            AHB_MON_ARM_I + AHB_MON_HBURST_REG_OFFSET);
-+    writel(hprot_reg_value,                             AHB_MON_ARM_I + AHB_MON_HPROT_REG_OFFSET);
-+
-+    writel(AHB_MON_MODE_RESET << AHB_MON_MODE_MODE_BIT, AHB_MON_DMA_A + AHB_MON_MODE_REG_OFFSET);
-+    writel(ahb_mon_hwrite << AHB_MON_HWRITE_COUNT_BIT,  AHB_MON_DMA_A + AHB_MON_HWRITE_REG_OFFSET);
-+    writel(0UL,                                         AHB_MON_DMA_A + AHB_MON_HADDR_LOW_REG_OFFSET);
-+    writel(~0UL,                                        AHB_MON_DMA_A + AHB_MON_HADDR_HIGH_REG_OFFSET);
-+    writel(hburst_reg_value,                            AHB_MON_DMA_A + AHB_MON_HBURST_REG_OFFSET);
-+    writel(hprot_reg_value,                             AHB_MON_DMA_A + AHB_MON_HPROT_REG_OFFSET);
-+
-+    writel(AHB_MON_MODE_RESET << AHB_MON_MODE_MODE_BIT, AHB_MON_DMA_B + AHB_MON_MODE_REG_OFFSET);
-+    writel(ahb_mon_hwrite << AHB_MON_HWRITE_COUNT_BIT,  AHB_MON_DMA_B + AHB_MON_HWRITE_REG_OFFSET);
-+    writel(0UL,                                         AHB_MON_DMA_B + AHB_MON_HADDR_LOW_REG_OFFSET);
-+    writel(~0UL,                                        AHB_MON_DMA_B + AHB_MON_HADDR_HIGH_REG_OFFSET);
-+    writel(hburst_reg_value,                            AHB_MON_DMA_B + AHB_MON_HBURST_REG_OFFSET);
-+    writel(hprot_reg_value,                             AHB_MON_DMA_B + AHB_MON_HPROT_REG_OFFSET);
-+
-+    writel(AHB_MON_MODE_RESET << AHB_MON_MODE_MODE_BIT, AHB_MON_LEON  + AHB_MON_MODE_REG_OFFSET);
-+    writel(ahb_mon_hwrite << AHB_MON_HWRITE_COUNT_BIT,  AHB_MON_LEON  + AHB_MON_HWRITE_REG_OFFSET);
-+    writel(0UL,                                         AHB_MON_LEON  + AHB_MON_HADDR_LOW_REG_OFFSET);
-+    writel(~0UL,                                        AHB_MON_LEON  + AHB_MON_HADDR_HIGH_REG_OFFSET);
-+    writel(hburst_reg_value,                            AHB_MON_LEON  + AHB_MON_HBURST_REG_OFFSET);
-+    writel(hprot_reg_value,                             AHB_MON_LEON  + AHB_MON_HPROT_REG_OFFSET);
-+
-+    writel(AHB_MON_MODE_RESET << AHB_MON_MODE_MODE_BIT, AHB_MON_USB   + AHB_MON_MODE_REG_OFFSET);
-+    writel(ahb_mon_hwrite << AHB_MON_HWRITE_COUNT_BIT,  AHB_MON_USB   + AHB_MON_HWRITE_REG_OFFSET);
-+    writel(0UL,                                         AHB_MON_USB   + AHB_MON_HADDR_LOW_REG_OFFSET);
-+    writel(~0UL,                                        AHB_MON_USB   + AHB_MON_HADDR_HIGH_REG_OFFSET);
-+    writel(hburst_reg_value,                            AHB_MON_USB   + AHB_MON_HBURST_REG_OFFSET);
-+    writel(hprot_reg_value,                             AHB_MON_USB   + AHB_MON_HPROT_REG_OFFSET);
-+
-+    writel(AHB_MON_MODE_RESET << AHB_MON_MODE_MODE_BIT, AHB_MON_MAC   + AHB_MON_MODE_REG_OFFSET);
-+    writel(ahb_mon_hwrite << AHB_MON_HWRITE_COUNT_BIT,  AHB_MON_MAC   + AHB_MON_HWRITE_REG_OFFSET);
-+    writel(0UL,                                         AHB_MON_MAC   + AHB_MON_HADDR_LOW_REG_OFFSET);
-+    writel(~0UL,                                        AHB_MON_MAC   + AHB_MON_HADDR_HIGH_REG_OFFSET);
-+    writel(hburst_reg_value,                            AHB_MON_MAC   + AHB_MON_HBURST_REG_OFFSET);
-+    writel(hprot_reg_value,                             AHB_MON_MAC   + AHB_MON_HPROT_REG_OFFSET);
-+
-+    writel(AHB_MON_MODE_RESET << AHB_MON_MODE_MODE_BIT, AHB_MON_PCI   + AHB_MON_MODE_REG_OFFSET);
-+    writel(ahb_mon_hwrite << AHB_MON_HWRITE_COUNT_BIT,  AHB_MON_PCI   + AHB_MON_HWRITE_REG_OFFSET);
-+    writel(0UL,                                         AHB_MON_PCI   + AHB_MON_HADDR_LOW_REG_OFFSET);
-+    writel(~0UL,                                        AHB_MON_PCI   + AHB_MON_HADDR_HIGH_REG_OFFSET);
-+    writel(hburst_reg_value,                            AHB_MON_PCI   + AHB_MON_HBURST_REG_OFFSET);
-+    writel(hprot_reg_value,                             AHB_MON_PCI   + AHB_MON_HPROT_REG_OFFSET);
-+
-+    // Start all the counters
-+    start_ahb_monitors();
-+}
-+
-+void restart_ahb_monitors(void)
-+{
-+    // Reset the counters
-+    writel(AHB_MON_MODE_RESET << AHB_MON_MODE_MODE_BIT, AHB_MON_ARM_D + AHB_MON_MODE_REG_OFFSET);
-+    writel(AHB_MON_MODE_RESET << AHB_MON_MODE_MODE_BIT, AHB_MON_ARM_I + AHB_MON_MODE_REG_OFFSET);
-+    writel(AHB_MON_MODE_RESET << AHB_MON_MODE_MODE_BIT, AHB_MON_DMA_A + AHB_MON_MODE_REG_OFFSET);
-+    writel(AHB_MON_MODE_RESET << AHB_MON_MODE_MODE_BIT, AHB_MON_DMA_B + AHB_MON_MODE_REG_OFFSET);
-+    writel(AHB_MON_MODE_RESET << AHB_MON_MODE_MODE_BIT, AHB_MON_LEON  + AHB_MON_MODE_REG_OFFSET);
-+    writel(AHB_MON_MODE_RESET << AHB_MON_MODE_MODE_BIT, AHB_MON_USB   + AHB_MON_MODE_REG_OFFSET);
-+    writel(AHB_MON_MODE_RESET << AHB_MON_MODE_MODE_BIT, AHB_MON_MAC   + AHB_MON_MODE_REG_OFFSET);
-+    writel(AHB_MON_MODE_RESET << AHB_MON_MODE_MODE_BIT, AHB_MON_PCI   + AHB_MON_MODE_REG_OFFSET);
-+
-+    // Start the counters
-+    start_ahb_monitors();
-+}
-+
-+void read_ahb_monitors(void)
-+{
-+    // Prepare the counters for reading
-+    writel(AHB_MON_MODE_IDLE << AHB_MON_MODE_MODE_BIT, AHB_MON_ARM_D + AHB_MON_MODE_REG_OFFSET);
-+    writel(AHB_MON_MODE_IDLE << AHB_MON_MODE_MODE_BIT, AHB_MON_ARM_I + AHB_MON_MODE_REG_OFFSET);
-+    writel(AHB_MON_MODE_IDLE << AHB_MON_MODE_MODE_BIT, AHB_MON_DMA_A + AHB_MON_MODE_REG_OFFSET);
-+    writel(AHB_MON_MODE_IDLE << AHB_MON_MODE_MODE_BIT, AHB_MON_DMA_B + AHB_MON_MODE_REG_OFFSET);
-+    writel(AHB_MON_MODE_IDLE << AHB_MON_MODE_MODE_BIT, AHB_MON_LEON  + AHB_MON_MODE_REG_OFFSET);
-+    writel(AHB_MON_MODE_IDLE << AHB_MON_MODE_MODE_BIT, AHB_MON_USB   + AHB_MON_MODE_REG_OFFSET);
-+    writel(AHB_MON_MODE_IDLE << AHB_MON_MODE_MODE_BIT, AHB_MON_MAC   + AHB_MON_MODE_REG_OFFSET);
-+    writel(AHB_MON_MODE_IDLE << AHB_MON_MODE_MODE_BIT, AHB_MON_PCI   + AHB_MON_MODE_REG_OFFSET);
-+
-+    // Read the counters
-+    printk("ARM-D: B=%u, T=%u, W=%u\n", readl(AHB_MON_ARM_D + AHB_MON_CYCLES_REG_OFFSET),
-+                                        readl(AHB_MON_ARM_D + AHB_MON_TRANSFERS_REG_OFFSET),
-+                                        readl(AHB_MON_ARM_D + AHB_MON_WAITS_REG_OFFSET));
-+
-+    printk("ARM-I: B=%u, T=%u, W=%u\n", readl(AHB_MON_ARM_I + AHB_MON_CYCLES_REG_OFFSET),
-+                                        readl(AHB_MON_ARM_I + AHB_MON_TRANSFERS_REG_OFFSET),
-+                                        readl(AHB_MON_ARM_I + AHB_MON_WAITS_REG_OFFSET));
-+
-+    printk("DMA-A: B=%u, T=%u, W=%u\n", readl(AHB_MON_DMA_A + AHB_MON_CYCLES_REG_OFFSET),
-+                                        readl(AHB_MON_DMA_A + AHB_MON_TRANSFERS_REG_OFFSET),
-+                                        readl(AHB_MON_DMA_A + AHB_MON_WAITS_REG_OFFSET));
-+
-+    printk("DMA-B: B=%u, T=%u, W=%u\n", readl(AHB_MON_DMA_B + AHB_MON_CYCLES_REG_OFFSET),
-+                                        readl(AHB_MON_DMA_B + AHB_MON_TRANSFERS_REG_OFFSET),
-+                                        readl(AHB_MON_DMA_B + AHB_MON_WAITS_REG_OFFSET));
-+
-+    printk("LEON:  B=%u, T=%u, W=%u\n", readl(AHB_MON_LEON  + AHB_MON_CYCLES_REG_OFFSET),
-+                                        readl(AHB_MON_LEON  + AHB_MON_TRANSFERS_REG_OFFSET),
-+                                        readl(AHB_MON_LEON  + AHB_MON_WAITS_REG_OFFSET));
-+
-+    printk("USB:   B=%u, T=%u, W=%u\n", readl(AHB_MON_USB   + AHB_MON_CYCLES_REG_OFFSET),
-+                                        readl(AHB_MON_USB   + AHB_MON_TRANSFERS_REG_OFFSET),
-+                                        readl(AHB_MON_USB   + AHB_MON_WAITS_REG_OFFSET));
-+
-+    printk("MAC:   B=%u, T=%u, W=%u\n", readl(AHB_MON_MAC   + AHB_MON_CYCLES_REG_OFFSET),
-+                                        readl(AHB_MON_MAC   + AHB_MON_TRANSFERS_REG_OFFSET),
-+                                        readl(AHB_MON_MAC   + AHB_MON_WAITS_REG_OFFSET));
-+
-+    printk("PCI:   B=%u, T=%u, W=%u\n", readl(AHB_MON_PCI   + AHB_MON_CYCLES_REG_OFFSET),
-+                                        readl(AHB_MON_PCI   + AHB_MON_TRANSFERS_REG_OFFSET),
-+                                        readl(AHB_MON_PCI   + AHB_MON_WAITS_REG_OFFSET));
-+}
-+#endif // CONFIG_HIPOX_AHB_MON
-+
-diff -Nurd linux-2.6.24/arch/arm/mach-hipox/cipher.c linux-2.6.24-oxe810/arch/arm/mach-hipox/cipher.c
---- linux-2.6.24/arch/arm/mach-hipox/cipher.c  1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mach-hipox/cipher.c   2008-06-11 17:47:55.000000000 +0200
-@@ -0,0 +1,362 @@
-+/* linux/arch/arm/mach-hipox/cipher.c
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include <linux/types.h>
-+#include <linux/sched.h>
-+#include <linux/types.h>
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/list.h>
-+#include <linux/device.h>
-+#include <linux/string.h>
-+#include <linux/sysdev.h>
-+#include <linux/highmem.h>
-+#include <asm/semaphore.h>
-+#include <asm/arch/cipher.h>
-+#include <asm/io.h>
-+#include <asm/arch/hardware.h>
-+#include <linux/dma-mapping.h>
-+#include <asm/arch/dma.h>
-+#include <asm-arm/page.h>
-+ 
++#include <linux/types.h>
++#include <linux/sched.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/list.h>
++#include <linux/device.h>
++#include <linux/string.h>
++#include <linux/sysdev.h>
++#include <linux/highmem.h>
++#include <asm/semaphore.h>
++#include <asm/arch/cipher.h>
++#include <asm/io.h>
++#include <asm/arch/hardware.h>
++#include <linux/dma-mapping.h>
++#include <asm/arch/dma.h>
++#include <asm-arm/page.h>
++ 
 +
 +#if 0
 +#define DPRINTK(fmt, args...) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args)
@@ -7152,9 +6224,9 @@ diff -Nurd linux-2.6.24/arch/arm/mach-hipox/cipher.c linux-2.6.24-oxe810/arch/ar
 + */
 +module_init(ox800_aeslrw_init);
 +module_exit(ox800_aeslrw_exit);
-diff -Nurd linux-2.6.24/arch/arm/mach-hipox/dma.c linux-2.6.24-oxe810/arch/arm/mach-hipox/dma.c
---- linux-2.6.24/arch/arm/mach-hipox/dma.c     1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mach-hipox/dma.c      2008-06-11 17:47:55.000000000 +0200
+diff -Nurd linux-2.6.24.4/arch/arm/mach-hipox/dma.c linux-2.6.24/arch/arm/mach-hipox/dma.c
+--- linux-2.6.24.4/arch/arm/mach-hipox/dma.c   1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/mach-hipox/dma.c     2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,2849 @@
 +/*
 + * linux/arch/arm/mach-hipox/dma.c
@@ -10005,9 +9077,9 @@ diff -Nurd linux-2.6.24/arch/arm/mach-hipox/dma.c linux-2.6.24-oxe810/arch/arm/m
 +EXPORT_SYMBOL(hipox_sata_dma_settings);
 +EXPORT_SYMBOL(hipox_dpe_rx_dma_settings);
 +EXPORT_SYMBOL(hipox_dpe_tx_dma_settings);
-diff -Nurd linux-2.6.24/arch/arm/mach-hipox/dpe_test.c linux-2.6.24-oxe810/arch/arm/mach-hipox/dpe_test.c
---- linux-2.6.24/arch/arm/mach-hipox/dpe_test.c        1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mach-hipox/dpe_test.c 2008-06-11 17:47:55.000000000 +0200
+diff -Nurd linux-2.6.24.4/arch/arm/mach-hipox/dpe_test.c linux-2.6.24/arch/arm/mach-hipox/dpe_test.c
+--- linux-2.6.24.4/arch/arm/mach-hipox/dpe_test.c      1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/mach-hipox/dpe_test.c        2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,3051 @@
 +/*
 + * /arch/=arm/mach-hipox/dpe-test.c
@@ -13060,12 +12132,12 @@ diff -Nurd linux-2.6.24/arch/arm/mach-hipox/dpe_test.c linux-2.6.24-oxe810/arch/
 +
 +/***************************************************************************/
 +module_init(ox800dpe_init);
-diff -Nurd linux-2.6.24/arch/arm/mach-hipox/gmac-napi.c linux-2.6.24-oxe810/arch/arm/mach-hipox/gmac-napi.c
---- linux-2.6.24/arch/arm/mach-hipox/gmac-napi.c       1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mach-hipox/gmac-napi.c        2008-06-11 17:47:55.000000000 +0200
-@@ -0,0 +1,3637 @@
+diff -Nurd linux-2.6.24.4/arch/arm/mach-hipox/gmac_desc.c linux-2.6.24/arch/arm/mach-hipox/gmac_desc.c
+--- linux-2.6.24.4/arch/arm/mach-hipox/gmac_desc.c     1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/mach-hipox/gmac_desc.c       2010-01-14 14:01:15.000000000 +0100
+@@ -0,0 +1,452 @@
 +/*
-+ * linux/arch/arm/mach-hipox/gmac.c
++ * linux/arch/arm/mach-hipox/gmac_desc.c
 + *
 + * Copyright (C) 2005 Oxford Semiconductor Ltd
 + *
@@ -13083,4909 +12155,4909 @@ diff -Nurd linux-2.6.24/arch/arm/mach-hipox/gmac-napi.c linux-2.6.24-oxe810/arch
 + * 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/crc32.h>
-+#include <linux/version.h>
-+#include <linux/init.h>
-+#include <linux/errno.h>
-+#include <linux/netdevice.h>
-+#include <linux/etherdevice.h>
-+#include <linux/dma-mapping.h>
 +#include <linux/delay.h>
-+#include <linux/in.h>
-+#include <net/ip.h>
-+#include <linux/tcp.h>
-+#include <linux/udp.h>
-+#include <asm/io.h>
-+#include <asm/arch/hardware.h>
-+#include <asm/arch/irqs.h>
-+
-+#ifdef CONFIG_LEON_COPRO
-+#include <asm/arch/leon-program.h>
-+#endif // CONFIG_LEON_COPRO
 +
 +//#define GMAC_DEBUG
 +#undef GMAC_DEBUG
 +
 +#include "gmac.h"
-+#include "gmac_ethtool.h"
-+#include "gmac_phy.h"
 +#include "gmac_desc.h"
-+#include "gmac_reg.h"
-+
-+//#define DUMP_REGS_ON_GMAC_UP
-+
-+#define MAX_GMAC_UNITS 1
-+
-+#define ALLOW_AUTONEG
 +
-+//#define ALLOW_OX800_1000M
-+
-+//#define SUPPORT_IPV6
-+
-+#ifdef CONFIG_LEON_COPRO
-+//#define TEST_COPRO
-+#define COPRO_RX_MITIGATION 0   /* No Rx mitigation in CoPro */
-+#define COPRO_RX_MITIGATION_FRAMES 5
-+#define COPRO_RX_MITIGATION_USECS 500
-+
-+#define COPRO_TX_QUEUE_NUM_ENTRIES  4
-+#define COPRO_CMD_QUEUE_NUM_ENTRIES 6
-+#define COPRO_MAX_QUEUED_TX_SKBS    16
-+#endif // CONFIG_LEON_COPRO
-+
-+#ifdef CONFIG_LEON_OFFLOAD_TX
-+#define NUM_RX_DMA_DESCRIPTORS  NUM_GMAC_DMA_DESCRIPTORS
-+#define NUM_TX_DMA_DESCRIPTORS  0
-+#else
-+#define NUM_RX_DMA_DESCRIPTORS (NUM_GMAC_DMA_DESCRIPTORS / 2)
-+#define NUM_TX_DMA_DESCRIPTORS (NUM_GMAC_DMA_DESCRIPTORS - NUM_RX_DMA_DESCRIPTORS)
-+#endif // CONFIG_LEON_OFFLOAD_TX
++void init_rx_desc_list(
++    gmac_desc_list_info_t    *desc_list,
++    volatile gmac_dma_desc_t *base_ptr,
++      gmac_dma_desc_t          *shadow_ptr,
++    int                       num_descriptors,
++      u16                       rx_buffer_length)
++{
++    int i;
 +
-+#if (((NUM_RX_DMA_DESCRIPTORS) + (NUM_TX_DMA_DESCRIPTORS)) > (NUM_GMAC_DMA_DESCRIPTORS))
-+#error "GMAC TX+RX descriptors exceed allocation"
-+#endif
++    desc_list->base_ptr = base_ptr;
++    desc_list->shadow_ptr = shadow_ptr;
++    desc_list->num_descriptors = num_descriptors;
++    desc_list->empty_count = num_descriptors;
++    desc_list->full_count = 0;
++    desc_list->r_index = 0;
++    desc_list->w_index = 0;
 +
-+#define DESC_SINCE_REFILL_LIMIT ((NUM_RX_DMA_DESCRIPTORS) / 4)
++      for (i=0; i < num_descriptors; ++i) {
++              gmac_dma_desc_t          *shadow = shadow_ptr + i;
++              volatile gmac_dma_desc_t *desc   = base_ptr + i;
 +
-+static const u32 MAC_BASE_OFFSET = 0x0000;
-+static const u32 DMA_BASE_OFFSET = 0x1000;
++              // Initialise the shadow descriptor
++              shadow->status = 0;
++              shadow->length = (rx_buffer_length << RDES1_RBS1_BIT);
++              if (i == (num_descriptors - 1)) {
++                      shadow->length |= (1UL << RDES1_RER_BIT);
++              }
++              shadow->buffer1 = 0;
++              shadow->buffer2 = 0;
 +
-+static const int MIN_PACKET_SIZE = 68;
-+static const int NORMAL_PACKET_SIZE = 1500;
-+static const int MAX_JUMBO = 9000;
++              // Copy the shadow descriptor into the real descriptor
++              desc->status  = shadow->status;
++              desc->length  = shadow->length;
++              desc->buffer1 = shadow->buffer1;
++              desc->buffer2 = shadow->buffer2;
++      }
++}
 +
-+#define RX_BUFFER_SIZE 796    // Must be multiple of 4, If not defined will size buffer to hold a single MTU-sized packet
++void init_tx_desc_list(
++    gmac_desc_list_info_t    *desc_list,
++    volatile gmac_dma_desc_t *base_ptr,
++      gmac_dma_desc_t          *shadow_ptr,
++    int                       num_descriptors)
++{
++    int i;
 +
-+#ifdef CONFIG_HIPOX_VERSION_0X800
-+static const int EXTRA_RX_SKB_SPACE = 24;     // Has extra 2 bytes of Rx payload csum
-+#else // CONFIG_HIPOX_VERSION_0X800
-+static const int EXTRA_RX_SKB_SPACE = 22;     // Ethernet header 14, VLAN 4, CRC 4
-+#endif // CONFIG_HIPOX_VERSION_0X800
++    desc_list->base_ptr = base_ptr;
++    desc_list->shadow_ptr = shadow_ptr;
++    desc_list->num_descriptors = num_descriptors;
++    desc_list->empty_count = num_descriptors;
++    desc_list->full_count = 0;
++    desc_list->r_index = 0;
++    desc_list->w_index = 0;
 +
-+// The amount of header to copy from a receive packet into the skb buffer
-+static const int GMAC_HLEN = 66;
++      for (i=0; i < num_descriptors; ++i) {
++              gmac_dma_desc_t          *shadow = shadow_ptr + i;
++              volatile gmac_dma_desc_t *desc   = base_ptr + i;
 +
-+#define GMAC_ALLOC_ORDER 0
-+static const int GMAC_ALLOC_SIZE = ((1 << GMAC_ALLOC_ORDER) * PAGE_SIZE);
++              // Initialise the shadow descriptor
++              shadow->status = 0;
++              shadow->length = (1UL << TDES1_IC_BIT);
++              if (i == (num_descriptors - 1)) {
++                      shadow->length |= (1UL << TDES1_TER_BIT);
++              }
++              shadow->buffer1 = 0;
++              shadow->buffer2 = 0;
 +
-+static const u32 AUTO_NEGOTIATION_WAIT_TIMEOUT_MS = 5000;
++              // Copy the shadow descriptor into the real descriptor
++              desc->status  = shadow->status;
++              desc->length  = shadow->length;
++              desc->buffer1 = shadow->buffer1;
++              desc->buffer2 = shadow->buffer2;
++      }
++}
 +
-+static const u32 NAPI_POLL_WEIGHT = 64;
-+static const u32 NAPI_OOM_POLL_INTERVAL_MS = 50;
++void rx_take_ownership(gmac_desc_list_info_t* desc_list)
++{
++    int i;
++    for (i=0; i < desc_list->num_descriptors; ++i) {
++        (desc_list->base_ptr + i)->status &= ~(1UL << RDES0_OWN_BIT);
++    }
 +
-+static const int WATCHDOG_TIMER_INTERVAL = 500*HZ/1000;
++    // Ensure all write to the descriptor shared with MAC have completed
++    wmb();
++}
 +
-+#define AUTO_NEG_MS_WAIT 500
-+static const int AUTO_NEG_INTERVAL = (AUTO_NEG_MS_WAIT)*HZ/1000;
-+static const int START_RESET_INTERVAL = 50*HZ/1000;
-+static const int RESET_INTERVAL = 10*HZ/1000;
++void tx_take_ownership(gmac_desc_list_info_t* desc_list)
++{
++    int i;
++    for (i=0; i < desc_list->num_descriptors; ++i) {
++        (desc_list->base_ptr + i)->status &= ~(1UL << TDES0_OWN_BIT);
++    }
 +
-+static const int GMAC_RESET_TIMEOUT_MS = 10000;
++    // Ensure all write to the descriptor shared with MAC have completed
++    wmb();
++}
 +
-+static int debug = 0;
++int set_rx_descriptor(
++    gmac_priv_t    *priv,
++    rx_frag_info_t *frag_info)
++{
++    int index = -1;
 +
-+MODULE_AUTHOR("Brian Clarke (Oxford Semiconductor Ltd)");
-+MODULE_DESCRIPTION("GMAC Network Driver");
-+MODULE_LICENSE("GPL");
-+MODULE_VERSION("v2.0");
++    // Is there a Rx descriptor available for writing by the CPU?
++    if (available_for_write(&priv->rx_gmac_desc_list_info)) {
++        // Setup the descriptor required to describe the RX packet
++        volatile gmac_dma_desc_t *descriptor;
++        gmac_dma_desc_t          *shadow;
 +
-+/* Ethernet MAC adr to assign to interface */
-+static int mac_adr[] = { 0x00, 0x30, 0xe0, 0x00, 0x00, 0x00 };
-+module_param_array(mac_adr, int, NULL, S_IRUGO);
++        // Get the index of the next RX descriptor available for writing by the CPU
++        index = priv->rx_gmac_desc_list_info.w_index;
 +
-+/* PHY type kernel cmdline options */
-+static int phy_is_rgmii = 0;
-+module_param(phy_is_rgmii, int, S_IRUGO);
++        // Get a pointer to the next RX descriptor available for writing by the CPU
++        descriptor = priv->rx_gmac_desc_list_info.base_ptr   + index;
++        shadow     = priv->rx_gmac_desc_list_info.shadow_ptr + index;
 +
-+/* Parse netdev kernel cmdline options */
-+static int __init do_setup(char *str)
-+{
-+    int i;
-+    int ints[5];    // Hold arg count and four args
-+      u32 mac_hi = 0;
-+      u32 mac_lo = 0;
++        // Set first buffer pointer to buffer from skb
++        descriptor->buffer1 = shadow->buffer1 = frag_info->phys_adr;
 +
-+      /* Get the netdev bootargs parameters */
-+    get_options(str, sizeof(ints)/sizeof(int), ints);
-+    for (i=1; i<=ints[0]; i++) {
-+        switch (i) {
-+            case 3:
-+                mac_hi = ints[i];
-+                break;
-+            case 4:
-+                mac_lo = ints[i];
-+                break;
-+        }
-+    }
++        // Remember the skb associated with the buffer
++        shadow->buffer2 = (u32)frag_info->page;
 +
-+      /* Break down the mac adr into its components */
-+      for (i=0; i < sizeof(mac_adr)/sizeof(int); i++) {
-+              if (i < sizeof(u32)) {
-+                      mac_adr[i] = ((mac_hi >> (((sizeof(u32)-1)-i)*8)) & 0xff);
-+              } else {
-+                      mac_adr[i] = ((mac_lo >> (((sizeof(u32)+1)-i)*8)) & 0xff);
-+              }
-+      }
++        // Ensure all prior writes to the descriptor shared with MAC have
++        // completed before setting the descriptor ownership flag to transfer
++        // ownership to the GMAC
++        wmb();
 +
-+      return 0;
-+}
-+__setup("netdev=",do_setup);
++        // Set RX descriptor status to transfer ownership to the GMAC
++        descriptor->status = (1UL << RDES0_OWN_BIT);
 +
-+#ifdef DUMP_REGS_ON_GMAC_UP
-+static void dump_mac_regs(u32 macBase, u32 dmaBase)
-+{
-+    int n = 0;
++        // Update the index of the next descriptor available for writing by the CPU
++        priv->rx_gmac_desc_list_info.w_index = (shadow->length & (1UL << RDES1_RER_BIT)) ? 0 : index + 1;
 +
-+    for (n=0; n<0x60; n+=4) {
-+        printk(KERN_INFO "MAC Register %08x (%08x) = %08x\n", n, macBase+n, readl(macBase+n));
++        // Account for the descriptor used to hold the new packet
++        --priv->rx_gmac_desc_list_info.empty_count;
++        ++priv->rx_gmac_desc_list_info.full_count;
 +    }
 +
-+    for (n=0; n<0x60; n+=4) {
-+        printk(KERN_INFO "DMA Register %08x (%08x) = %08x\n", n, dmaBase+n, readl(dmaBase+n));
-+    }
++    return index;
 +}
-+#endif // DUMP_REGS_ON_GMAC_UP
-+
-+#ifdef CONFIG_LEON_COPRO
-+static struct semaphore copro_update_semaphore;
 +
-+static void copro_update_callback(volatile gmac_cmd_que_ent_t* entry)
++int get_rx_descriptor(
++    gmac_priv_t    *priv,
++    int            *last,
++    u32            *status,
++    rx_frag_info_t *frag_info)
 +{
-+    up(&copro_update_semaphore);
-+}
-+
-+static struct semaphore copro_start_semaphore;
++      int                       index;
++      volatile gmac_dma_desc_t *descriptor;
++      gmac_dma_desc_t          *shadow;
++      u32                       desc_status;
 +
-+static void copro_start_callback(volatile gmac_cmd_que_ent_t* entry)
-+{
-+    up(&copro_start_semaphore);
-+}
++      if (!priv->rx_gmac_desc_list_info.full_count) {
++              return -2;
++      }
 +
-+static struct semaphore copro_rx_enable_semaphore;
++      // Get the index of the descriptor released the longest time ago by the GMAC DMA 
++    index       = priv->rx_gmac_desc_list_info.r_index;
++      descriptor  = priv->rx_gmac_desc_list_info.base_ptr   + index;
++      shadow      = priv->rx_gmac_desc_list_info.shadow_ptr + index;
 +
-+static void copro_rx_enable_callback(volatile gmac_cmd_que_ent_t* entry)
-+{
-+    up(&copro_rx_enable_semaphore);
-+}
-+#endif // CONFIG_LEON_COPRO
++      if (status && *status) {
++              desc_status = *status;
++      } else {
++              desc_status = descriptor->status;
++      }
 +
-+static void gmac_int_en_set(
-+    gmac_priv_t *priv,
-+    u32          mask)
-+{
-+    unsigned long irq_flags = 0;
++    if (desc_status & (1UL << RDES0_OWN_BIT)) {
++              return -1;
++      }
 +
-+#ifdef CONFIG_LEON_COPRO
-+    int cmd_queue_result = -1;
-+    while (cmd_queue_result) {
-+        if (in_irq())
-+            spin_lock(&priv->cmd_que_lock_);
-+        else
-+            spin_lock_irqsave(&priv->cmd_que_lock_, irq_flags);
++      // Update the index of the next descriptor with which the GMAC DMA may have finished
++      priv->rx_gmac_desc_list_info.r_index = (shadow->length & (1UL << RDES1_RER_BIT)) ? 0 : index + 1;
 +
-+        cmd_queue_result = cmd_que_queue_cmd(&priv->cmd_queue_, GMAC_CMD_INT_EN_SET, mask, 0);
++      // Account for the descriptor which is now no longer waiting to be processed by the CPU
++      ++priv->rx_gmac_desc_list_info.empty_count;
++      --priv->rx_gmac_desc_list_info.full_count;
 +
-+        if (in_irq())
-+            spin_unlock(&priv->cmd_que_lock_);
-+        else
-+            spin_unlock_irqrestore(&priv->cmd_que_lock_, irq_flags);
-+    }
++      // Get packet details from the descriptor
++      frag_info->page = (struct page*)(shadow->buffer2);
++      frag_info->phys_adr = shadow->buffer1;
++      frag_info->length = get_rx_length(desc_status);
 +
-+    // Interrupt the CoPro so it sees the new command
-+    writel(1UL << COPRO_SEM_INT_CMD, SYS_CTRL_SEMA_SET_CTRL);
-+#else
-+    if (in_irq())
-+        spin_lock(&priv->cmd_que_lock_);
-+    else
-+        spin_lock_irqsave(&priv->cmd_que_lock_, irq_flags);
++      // Is this descriptor the last contributing to a packet
++      *last = desc_status & (1UL << RDES0_LS_BIT);
 +
-+    dma_reg_set_mask(priv, DMA_INT_ENABLE_REG, mask);
++      // Accumulate the status
++      if (status && !*status) {
++              *status = desc_status;
++      }
 +
-+    if (in_irq())
-+        spin_unlock(&priv->cmd_que_lock_);
-+    else
-+        spin_unlock_irqrestore(&priv->cmd_que_lock_, irq_flags);
-+#endif // CONFIG_LEON_COPRO
++    return index;
 +}
 +
-+#ifdef CONFIG_LEON_COPRO
-+static struct semaphore copro_int_clr_semaphore;
-+static unsigned long    copro_int_clr_return;
-+
-+static void copro_int_clr_callback(volatile gmac_cmd_que_ent_t* entry)
++static inline int num_descriptors_needed(u16 length)
 +{
-+    copro_int_clr_return = entry->operand_;
-+    up(&copro_int_clr_semaphore);
++      static const int GMAC_MAX_DESC_ORDER = 11;
++      static const u16 GMAC_MAX_DESC_MASK = ((1 << (GMAC_MAX_DESC_ORDER)) - 1);
++
++      int count = length >> GMAC_MAX_DESC_ORDER;
++      if (length & GMAC_MAX_DESC_MASK) {
++              ++count;
++      }
++      if ((count * max_descriptor_length()) < length) {
++              ++count;
++      }
++
++      return count;
 +}
-+#endif // CONFIG_LEON_COPRO
 +
-+static void gmac_int_en_clr(
-+    gmac_priv_t *priv,
-+    u32          mask,
-+    u32         *new_value,
-+      int          in_atomic)
++int set_tx_descriptor(
++    gmac_priv_t    *priv,
++    struct sk_buff *skb,
++    tx_frag_info_t *frag_info,
++    int             frag_count,
++    int             use_hw_csum)
 +{
-+#ifdef CONFIG_LEON_COPRO
-+    unsigned long irq_flags = 0;
-+
-+    int cmd_queue_result = -1;
-+    while (cmd_queue_result) {
-+        if (in_irq())
-+            spin_lock(&priv->cmd_que_lock_);
-+        else
-+            spin_lock_irqsave(&priv->cmd_que_lock_, irq_flags);
++      int first_descriptor_index = -1;
++      int num_descriptors = frag_count;
++    int frag_index = 0;
++      int check_oversized_frags = priv->netdev->mtu >= (max_descriptor_length() - ETH_HLEN);
 +
-+        cmd_queue_result = cmd_que_queue_cmd(&priv->cmd_queue_, GMAC_CMD_INT_EN_CLR, mask, copro_int_clr_callback);
++      if (unlikely(check_oversized_frags)) {
++              // Calculate the number of extra descriptors required due to fragments
++              // being longer than the maximum buffer size that can be described by a
++              // single descriptor
++              num_descriptors = 0;
++              do {
++                      // How many descriptors are required to describe the fragment?
++                      num_descriptors += num_descriptors_needed(frag_info[frag_index].length);
++              } while (++frag_index < frag_count);
++      }
 +
-+        if (in_irq())
-+            spin_unlock(&priv->cmd_que_lock_);
-+        else
-+            spin_unlock_irqrestore(&priv->cmd_que_lock_, irq_flags);
++    // Are sufficicent descriptors available for writing by the CPU?
++    if (available_for_write(&priv->tx_gmac_desc_list_info) < num_descriptors) {
++        return -1;
 +    }
 +
-+    // Interrupt the CoPro so it sees the new command
-+    writel(1UL << COPRO_SEM_INT_CMD, SYS_CTRL_SEMA_SET_CTRL);
++      {
++              volatile gmac_dma_desc_t *previous_descriptor = 0;
++              gmac_dma_desc_t          *previous_shadow = 0;
++              volatile gmac_dma_desc_t *descriptors[num_descriptors];
++              int desc_index = 0;
 +
-+    if (new_value) {
-+        // Wait until the CoPro acknowledges that it has stopped
-+        if (in_atomic) {
-+            while (down_trylock(&copro_int_clr_semaphore)) {
-+                udelay(100);
-+            }
-+        } else {
-+            down_interruptible(&copro_int_clr_semaphore);
-+        }
-+        *new_value = copro_int_clr_return;
-+    }
-+#else
-+    unsigned long temp;
-+    unsigned long irq_flags = 0;
++              frag_index = 0;
++              do {
++                      int        last_frag   = (frag_index == (frag_count - 1));
++                      u16        part_length = frag_info[frag_index].length;
++                      dma_addr_t phys_adr    = frag_info[frag_index].phys_adr;
++                      int        part        = 0;
++                      int        parts       = 1;
 +
-+    if (in_irq())
-+        spin_lock(&priv->cmd_que_lock_);
-+    else
-+        spin_lock_irqsave(&priv->cmd_que_lock_, irq_flags);
++                      if (unlikely(check_oversized_frags)) {
++                              // How many descriptors are required to describe the fragment?
++                              parts = num_descriptors_needed(part_length);
++                      }
 +
-+    temp = dma_reg_clear_mask(priv, DMA_INT_ENABLE_REG, mask);
++                      // Setup a descriptor for each part of the fragment that can be
++                      // described by a single descriptor
++                      do {
++                              int                       last_part  = (part == (parts - 1));
++                              int                       index      = priv->tx_gmac_desc_list_info.w_index;
++                              volatile gmac_dma_desc_t *descriptor = priv->tx_gmac_desc_list_info.base_ptr + index;
++                              gmac_dma_desc_t          *shadow     = priv->tx_gmac_desc_list_info.shadow_ptr + index;
++                              u32                       length     = shadow->length;
++                              u32                       buffer2    = 0;
 +
-+    if (in_irq())
-+        spin_unlock(&priv->cmd_que_lock_);
-+    else
-+        spin_unlock_irqrestore(&priv->cmd_que_lock_, irq_flags);
++                              // Remember descriptor pointer for final passing of ownership to GMAC
++                              descriptors[desc_index++] = descriptor;
 +
-+    if (new_value) {
-+        *new_value = temp;
-+    }
-+#endif
-+}
++                              // May have a second chained descriptor, but never a second buffer,
++                              // so clear the flag indicating whether there is a chained descriptor
++                              length &= ~(1UL << TDES1_TCH_BIT);
 +
-+/**
-+ * May be invoked from either ISR or process context, so locking must be
-+ * invoked appropriate to the return from in_irq()
-+ */
-+static void change_rx_enable(
-+    gmac_priv_t *priv,
-+    u32          start,
-+    int          waitForAck,
-+      int          in_atomic)
-+{
-+#ifdef CONFIG_LEON_COPRO
-+    unsigned long irq_flags = 0;
-+    int cmd_queue_result = -1;
++                              // Clear the first/last descriptor flags
++                              length &= ~((1UL << TDES1_LS_BIT) | (1UL << TDES1_FS_BIT));
 +
-+    while (cmd_queue_result) {
-+        if (in_irq())
-+            spin_lock(&priv->cmd_que_lock_);
-+        else
-+            spin_lock_irqsave(&priv->cmd_que_lock_, irq_flags);
++                              // Set the Tx checksum mode
++                              length &= ~(((1UL << TDES1_CIC_NUM_BITS) - 1) << TDES1_CIC_BIT);
++                              if (use_hw_csum) {
++                                      // Don't want full mode as network stack will have already
++                                      // computed the TCP/UCP pseudo header and placed in into the
++                                      // TCP/UCP checksum field
++                                      length |= (TDES1_CIC_PAYLOAD << TDES1_CIC_BIT);
++                              }
++                              // Set fragment buffer length
++                              length &= ~(((1UL << TDES1_TBS1_NUM_BITS) - 1) << TDES1_TBS1_BIT);
++                              length |= ((part_length > max_descriptor_length() ? max_descriptor_length() : part_length) << TDES1_TBS1_BIT);
 +
-+        // Request the CoPro to start/stop GMAC receiver
-+        cmd_queue_result =
-+            cmd_que_queue_cmd(&priv->cmd_queue_,
-+                              GMAC_CMD_CHANGE_RX_ENABLE,
-+                              start,
-+                              waitForAck ? copro_rx_enable_callback : 0);
++                              // Set fragment buffer address
++                              descriptor->buffer1 = shadow->buffer1 = phys_adr;
 +
-+        if (in_irq())
-+            spin_unlock(&priv->cmd_que_lock_);
-+        else
-+            spin_unlock_irqrestore(&priv->cmd_que_lock_, irq_flags);
-+    }
++                              if (previous_shadow) {
++                                      // Make the previous descriptor chain to the current one
++                                      previous_shadow->length |= (1UL << TDES1_TCH_BIT);
++                                      previous_descriptor->length = previous_shadow->length;
 +
-+    // Interrupt the CoPro so it sees the new command
-+    writel(1UL << COPRO_SEM_INT_CMD, SYS_CTRL_SEMA_SET_CTRL);
++                                      previous_shadow->buffer2 |= descriptors_virt_to_phys((u32)descriptor);
++                                      previous_descriptor->buffer2 = previous_shadow->buffer2;
++                              }
 +
-+    if (waitForAck) {
-+        // Wait until the CoPro acknowledges that the receiver has been stopped
-+        if (in_atomic) {
-+            while (down_trylock(&copro_rx_enable_semaphore)) {
-+                udelay(100);
-+            }
-+        } else {
-+            down_interruptible(&copro_rx_enable_semaphore);
-+        }
-+    }
-+#else // CONFIG_LEON_COPRO
-+    start ? dma_reg_set_mask(priv, DMA_OP_MODE_REG, 1UL << DMA_OP_MODE_SR_BIT) :
-+            dma_reg_clear_mask(priv, DMA_OP_MODE_REG, 1UL << DMA_OP_MODE_SR_BIT);
-+#endif // CONFIG_LEON_COPRO
-+}
++                              // Is this the first desciptor for the packet?
++                              if (!frag_index && !part) {
++                                      // Need to return index of first descriptor used for packet
++                                      first_descriptor_index = index;
 +
-+/**
-+ * Invoked from the watchdog timer action routine which runs as softirq, so
-+ * must disable interrupts when obtaining locks
-+ */
-+static void change_gig_mode(gmac_priv_t *priv)
-+{
-+      unsigned int is_gig = priv->mii.using_1000;
++                                      // Set flag indicating is first descriptor for packet
++                                      length |= (1UL << TDES1_FS_BIT);
++                              }
 +
-+#ifdef CONFIG_LEON_COPRO
-+    unsigned long irq_flags = 0;
-+    int cmd_queue_result = -1;
++                              // Is this the last descriptor for the packet?
++                              if (last_frag && last_part) {
++                                      // Store the skb pointer with the last descriptor for packet, in
++                                      // which the second buffer address will be unused as we do not use
++                                      // second buffers and only intermedate buffers may use the chained
++                                      // descriptor address
++                                      buffer2 = (u32)skb;
 +
-+    while (cmd_queue_result) {
-+        spin_lock_irqsave(&priv->cmd_que_lock_, irq_flags);
-+        // Request the CoPro to change gigabit mode
-+        cmd_queue_result = cmd_que_queue_cmd(&priv->cmd_queue_, GMAC_CMD_CHANGE_GIG_MODE, is_gig, 0);
-+        spin_unlock_irqrestore(&priv->cmd_que_lock_, irq_flags);
-+    }
++                                      // Set flag indicating is last descriptor for packet
++                                      length |= (1UL << TDES1_LS_BIT);
++                              } else {
++                                      // For descriptor chaining need to remember previous descriptor
++                                      previous_descriptor = descriptor;
++                                      previous_shadow = shadow;
 +
-+    // Interrupt the CoPro so it sees the new command
-+    writel(1UL << COPRO_SEM_INT_CMD, SYS_CTRL_SEMA_SET_CTRL);
-+#else // CONFIG_LEON_COPRO
-+      static const int MAX_TRIES = 1000;
-+      int tries = 0;
++                                      // Is this descriptor not the last describing a single fragment
++                                      // buffer?
++                                      if (!last_part) {
++                                              // This descriptor does not own the fragment buffer, so use
++                                              // the (h/w ignored) lsb of buffer2 to encode this info.
++                                              buffer2 = 1;
 +
-+    // Mask to extract the transmit status field from the status register
-+    u32 ts_mask = ((1UL << DMA_STATUS_TS_NUM_BITS) - 1) << DMA_STATUS_TS_BIT;
++                                              // Update the fragment buffer part details
++                                              part_length -= max_descriptor_length();
++                                              phys_adr    += max_descriptor_length();
++                                      }
++                              }
 +
-+    // Must stop transmission in order to change store&forward mode
-+    dma_reg_clear_mask(priv, DMA_OP_MODE_REG, (1UL << DMA_OP_MODE_ST_BIT));
++                              // Write the assembled length descriptor entry to the descriptor
++                              descriptor->length = shadow->length = length;
 +
-+    // Transmission only stops after current Tx frame has completed trans-
-+    // mission, so wait for the Tx state machine to enter the stopped state
-+    while ((dma_reg_read(priv, DMA_STATUS_REG) & ts_mask) != (DMA_STATUS_TS_STOPPED << DMA_STATUS_TS_BIT)) {
-+              mdelay(1);
-+              if (unlikely(++tries == MAX_TRIES)) {
-+                      break;
-+              }
-+      }
++                              // Write the assembled buffer2 descriptor entry to the descriptor
++                              shadow->buffer2 = buffer2;
 +
-+      if (unlikely(tries == MAX_TRIES)) {
-+              printk(KERN_WARNING "Timed out of wait for Tx to stop\n");
++                              // Update the index of the next descriptor available for writing by the CPU
++                              priv->tx_gmac_desc_list_info.w_index = (length & (1UL << TDES1_TER_BIT)) ? 0 : index + 1;
++                      } while (++part < parts);
++              } while (++frag_index < frag_count);
++
++              // Ensure all prior writes to the descriptors shared with MAC have
++              // completed before setting the descriptor ownership flags to transfer
++              // ownership to the GMAC
++              wmb();
++
++              // Transfer descriptors to GMAC's ownership in reverse order, so when
++              // GMAC begins processing the first descriptor all others are already
++              // owned by the GMAC
++              for (desc_index = (num_descriptors - 1); desc_index >= 0; --desc_index) {
++                      descriptors[desc_index]->status = (1UL << TDES0_OWN_BIT);
++              }
 +      }
 +
-+    if (is_gig) {
-+        mac_reg_clear_mask(priv, MAC_CONFIG_REG, (1UL << MAC_CONFIG_PS_BIT));
-+#ifdef CONFIG_HIPOX_VERSION_0X800
-+        // In gigabit mode the OX800 cannot support the required data rate to
-+        // the GMAC, so must use store&forward and OX800 doesn't support Tx
-+              // checksumming in the GMAC
-+        dma_reg_set_mask(priv, DMA_OP_MODE_REG, (1UL << DMA_OP_MODE_SF_BIT));
-+#endif // CONFIG_HIPOX_VERSION_0X800
-+    } else {
-+        mac_reg_set_mask(priv, MAC_CONFIG_REG, (1UL << MAC_CONFIG_PS_BIT));
-+#ifdef CONFIG_HIPOX_VERSION_0X800
-+        dma_reg_clear_mask(priv, DMA_OP_MODE_REG, (1UL << DMA_OP_MODE_SF_BIT));
-+#endif // CONFIG_HIPOX_VERSION_0X800
-+    }
++    // Account for the number of descriptors used to hold the new packet
++    priv->tx_gmac_desc_list_info.empty_count -= (num_descriptors);
++    priv->tx_gmac_desc_list_info.full_count  += (num_descriptors);
 +
-+    // Re-start transmission after store&forward change applied
-+    dma_reg_set_mask(priv, DMA_OP_MODE_REG, (1UL << DMA_OP_MODE_ST_BIT));
-+#endif // CONFIG_LEON_COPRO
++    return first_descriptor_index;
 +}
 +
-+/**
-+ * Invoked from the watchdog timer action routine which runs as softirq, so
-+ * must disable interrupts when obtaining locks
-+ */
-+static void change_pause_mode(gmac_priv_t *priv)
++int get_tx_descriptor(
++    gmac_priv_t     *priv,
++    struct sk_buff **skb,
++    u32             *status,
++    tx_frag_info_t  *frag_info,
++    int             *buffer_owned)
 +{
-+#ifdef CONFIG_LEON_COPRO
-+      unsigned int enable_pause = priv->mii.using_pause;
-+    unsigned long irq_flags = 0;
-+    int cmd_queue_result = -1;
++    int index = -1;
++      u32 local_status;
 +
-+    while (cmd_queue_result) {
-+        spin_lock_irqsave(&priv->cmd_que_lock_, irq_flags);
-+        // Request the CoPro to change pause mode
-+        cmd_queue_result = cmd_que_queue_cmd(&priv->cmd_queue_, GMAC_CMD_CHANGE_PAUSE_MODE, enable_pause, 0);
-+        spin_unlock_irqrestore(&priv->cmd_que_lock_, irq_flags);
-+    }
++    // Find the first available Tx descriptor
++    if (tx_available_for_read(&priv->tx_gmac_desc_list_info, &local_status)) {
++        gmac_dma_desc_t *shadow;
++        u32 length;
++        u32 buffer2;
 +
-+    // Interrupt the CoPro so it sees the new command
-+    writel(1UL << COPRO_SEM_INT_CMD, SYS_CTRL_SEMA_SET_CTRL);
-+#else // CONFIG_LEON_COPRO
-+#ifndef CONFIG_HIPOX_VERSION_0X800
-+      unsigned int enable_pause = priv->mii.using_pause;
++        // Get the descriptor released the longest time ago by the GMAC DMA
++        index = priv->tx_gmac_desc_list_info.r_index;
++        shadow = priv->tx_gmac_desc_list_info.shadow_ptr + index;
 +
-+    if (enable_pause) {
-+        mac_reg_set_mask(priv, MAC_FLOW_CNTL_REG, (1UL << MAC_FLOW_CNTL_TFE_BIT));
-+    } else {
-+        mac_reg_clear_mask(priv, MAC_FLOW_CNTL_REG, (1UL << MAC_FLOW_CNTL_TFE_BIT));
++        // Get the length of the buffer
++        length = shadow->length;
++        frag_info->length = ((length >> TDES1_TBS1_BIT) & ((1UL << TDES1_TBS1_NUM_BITS) - 1));
++
++        // Get a pointer to the buffer
++        frag_info->phys_adr = shadow->buffer1;
++
++              // Get buffer ownership or skb info
++        buffer2 = shadow->buffer2;
++
++        // Check that chained buffer not is use before setting skb from buffer2
++        if (!(length & (1UL << TDES1_TCH_BIT))) {
++            *skb = (struct sk_buff*)buffer2;
++                      *buffer_owned = 1;
++        } else {
++            // The lsb (h/w ignored) is used to encode buffer ownership
++            *buffer_owned = !(buffer2 & 1);
++                      *skb = 0;
++        }
++
++        // Accumulate status
++        if (status) {
++            *status |= local_status;
++        }
++
++        // Update the index of the next descriptor with which the GMAC DMA may have finished
++        priv->tx_gmac_desc_list_info.r_index = (length & (1UL << TDES1_TER_BIT)) ? 0 : index + 1;
++
++        // Account for the descriptor which is now no longer waiting to be processed by the CPU
++        ++priv->tx_gmac_desc_list_info.empty_count;
++        --priv->tx_gmac_desc_list_info.full_count;
 +    }
-+#endif // !CONFIG_HIPOX_VERSION_0X800
-+#endif // CONFIG_LEON_COPRO
-+}
 +
-+static void refill_rx_ring(struct net_device *dev)
-+{
-+    gmac_priv_t *priv = (gmac_priv_t*)netdev_priv(dev);
-+      int filled = 0;
++    return index;
++}
 +
-+      if (unlikely(priv->rx_buffers_per_page)) {
-+              // Receive into pages
-+              struct page *page = 0;
-+              int offset = 0;
-+              dma_addr_t phys_adr = 0;
+diff -Nurd linux-2.6.24.4/arch/arm/mach-hipox/gmac_desc.h linux-2.6.24/arch/arm/mach-hipox/gmac_desc.h
+--- linux-2.6.24.4/arch/arm/mach-hipox/gmac_desc.h     1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/mach-hipox/gmac_desc.h       2010-01-14 14:01:15.000000000 +0100
+@@ -0,0 +1,315 @@
++/*
++ * linux/arch/arm/mach-hipox/gmac_desc.h
++ *
++ * Copyright (C) 2005 Oxford Semiconductor Ltd
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++#if !defined(__GMAC_DESC_H__)
++#define __GMAC_DESC_H__
 +
-+              // While there are empty RX descriptor ring slots
-+              while (1) {
-+                      int available;
-+                      int desc;
-+                      rx_frag_info_t frag_info;
++#include <asm/types.h>
++#include "gmac.h"
 +
-+                      // Have we run out of space in the current page?
-+                      if (offset + NET_IP_ALIGN + priv->rx_buffer_size_ > GMAC_ALLOC_SIZE) {
-+                              page = 0;
-+                              offset = 0;
-+                      }
++typedef enum rdes0 {
++    RDES0_OWN_BIT  = 31,
++    RDES0_AFM_BIT  = 30,
++    RDES0_FL_BIT   = 16,
++    RDES0_ES_BIT   = 15,
++    RDES0_DE_BIT   = 14,
++    RDES0_SAF_BIT  = 13,
++    RDES0_LE_BIT   = 12,
++    RDES0_OE_BIT   = 11,
++    RDES0_IPC_BIT  = 10,
++    RDES0_FS_BIT   = 9,
++    RDES0_LS_BIT   = 8,
++    RDES0_VLAN_BIT = 7,
++    RDES0_LC_BIT   = 6,
++    RDES0_FT_BIT   = 5,
++    RDES0_RWT_BIT  = 4,
++    RDES0_RE_BIT   = 3,
++    RDES0_DRE_BIT  = 2,
++    RDES0_CE_BIT   = 1,
++    RDES0_PCE_BIT  = 0
++} rdes0_t;
 +
-+                      if (!page) {
-+                              // Start a new page
-+                              available = available_for_write(&priv->rx_gmac_desc_list_info);
-+                              if (available < priv->rx_buffers_per_page) {
-+                                      break;
-+                              }
++#define RX_DESC_STATUS_FL_NUM_BITS 14
 +
-+                              // Allocate a page to hold a received packet
-+                              page = alloc_pages(GFP_ATOMIC, GMAC_ALLOC_ORDER);
-+                              if (unlikely(page == NULL)) {
-+                                      printk(KERN_WARNING "refill_rx_ring() Could not alloc page\n");
-+                                      break;
-+                              }
++typedef enum rdes1 {
++    RDES1_DIC_BIT  = 31,
++    RDES1_RER_BIT  = 25,
++    RDES1_RCH_BIT  = 24,
++    RDES1_RBS2_BIT = 11,
++    RDES1_RBS1_BIT = 0,
++} rdes1_t;
 +
-+                              // Get a consistent DMA mapping for the entire page that will be
-+                              // DMAed to - causing an invalidation of any entries in the CPU's
-+                              // cache covering the memory region
-+                              phys_adr = dma_map_page(0, page, 0, GMAC_ALLOC_SIZE, DMA_FROM_DEVICE);
-+                              BUG_ON(dma_mapping_error(phys_adr));
-+                      } else {
-+                              // Using the current page again
-+                              get_page(page);
-+                      }
++#define RX_DESC_LENGTH_RBS2_NUM_BITS 11
++#define RX_DESC_LENGTH_RBS1_NUM_BITS 11
 +
-+                      // Ensure IP header is quad aligned
-+                      offset += NET_IP_ALIGN;
-+                      frag_info.page = page;
-+                      frag_info.length = priv->rx_buffer_size_;
-+                      frag_info.phys_adr = phys_adr + offset;
++typedef enum tdes0 {
++    TDES0_OWN_BIT = 31,
++    TDES0_IHE_BIT = 16,
++    TDES0_ES_BIT  = 15,
++    TDES0_JT_BIT  = 14,
++    TDES0_FF_BIT  = 13,
++    TDES0_PCE_BIT = 12,
++    TDES0_LOC_BIT = 11,
++    TDES0_NC_BIT  = 10,
++    TDES0_LC_BIT  = 9,
++    TDES0_EC_BIT  = 8,
++    TDES0_VF_BIT  = 7,
++    TDES0_CC_BIT  = 3,
++    TDES0_ED_BIT  = 2,
++    TDES0_UF_BIT  = 1,
++    TDES0_DB_BIT  = 0
++} tdes0_t;
 +
-+                      // Try to associate a descriptor with the fragment info
-+                      desc = set_rx_descriptor(priv, &frag_info);
-+                      if (desc >= 0) {
-+                              filled = 1;
-+                      } else {
-+                              // Failed to associate the descriptor, so release the DMA mapping
-+                              // for the socket buffer
-+                              dma_unmap_page(0, frag_info.phys_adr, frag_info.length, DMA_FROM_DEVICE);
++#define TDES0_CC_NUM_BITS 4
 +
-+                              // No more RX descriptor ring entries to refill
-+                              break;
-+                      }
++typedef enum tdes1 {
++    TDES1_IC_BIT   = 31,
++    TDES1_LS_BIT   = 30,
++    TDES1_FS_BIT   = 29,
++    TDES1_CIC_BIT  = 27,
++    TDES1_DC_BIT   = 26,
++    TDES1_TER_BIT  = 25,
++    TDES1_TCH_BIT  = 24,
++    TDES1_DP_BIT   = 23,
++    TDES1_TBS2_BIT = 11,
++    TDES1_TBS1_BIT = 0
++} tdes1_t;
 +
-+                      // Account for the space used in the current page
-+                      offset += frag_info.length;
++#define TDES1_CIC_NUM_BITS  2
++#define TDES1_TBS2_NUM_BITS 11
++#define TDES1_TBS1_NUM_BITS 11
 +
-+                      // Start next packet on a cacheline boundary
-+                      offset = SKB_DATA_ALIGN(offset);
-+              }
-+      } else {
-+              // Preallocate MTU-sized SKBs
-+              while (1) {
-+                      struct sk_buff *skb;
-+                      rx_frag_info_t frag_info;
-+                      int desc;
++#define TDES1_CIC_NONE    0
++#define TDES1_CIC_HDR     1
++#define TDES1_CIC_PAYLOAD 2
++#define TDES1_CIC_FULL    3
 +
-+                      if (!available_for_write(&priv->rx_gmac_desc_list_info)) {
-+                              break;
-+                      }
++extern void init_rx_desc_list(
++    gmac_desc_list_info_t    *desc_list,
++    volatile gmac_dma_desc_t *base_ptr,
++      gmac_dma_desc_t          *shadow_ptr,
++    int                       num_descriptors,
++      u16                       rx_buffer_length);
 +
-+                      // Allocate a new skb for the descriptor ring which is large enough
-+                      // for any packet received from the link
-+                      skb = dev_alloc_skb(priv->rx_buffer_size_ + NET_IP_ALIGN);
-+                      if (!skb) {
-+                              // Can't refill any more RX descriptor ring entries
-+                              break;
-+                      } else {
-+                              // Despite what the comments in the original code from Synopsys
-+                              // claimed, the GMAC DMA can cope with non-quad aligned buffers
-+                              // - it will always perform quad transfers but zero/ignore the
-+                              // unwanted bytes.
-+                              skb_reserve(skb, NET_IP_ALIGN);
-+                      }
++extern void init_tx_desc_list(
++    gmac_desc_list_info_t    *desc_list,
++    volatile gmac_dma_desc_t *base_ptr,
++      gmac_dma_desc_t          *shadow_ptr,
++    int                       num_descriptors);
 +
-+                      // Get a consistent DMA mapping for the memory to be DMAed to
-+                      // causing invalidation of any entries in the CPU's cache covering
-+                      // the memory region
-+                      frag_info.page = (struct page*)skb;
-+                      frag_info.length = skb_tailroom(skb);
-+                      frag_info.phys_adr = dma_map_single(0, skb->tail, frag_info.length, DMA_FROM_DEVICE);
-+                      BUG_ON(dma_mapping_error(frag_info.phys_adr));
++/** Force ownership of all descriptors in the specified list to being owned by
++ *  the CPU
++ */
++extern void rx_take_ownership(gmac_desc_list_info_t* desc_list);
 +
-+                      // Associate the skb with the descriptor
-+                      desc = set_rx_descriptor(priv, &frag_info);
-+                      if (desc >= 0) {
-+                              filled = 1;
-+                      } else {
-+                              // No, so release the DMA mapping for the socket buffer
-+                              dma_unmap_single(0, frag_info.phys_adr, frag_info.length, DMA_FROM_DEVICE);
++/** Force ownership of all descriptors in the specified list to being owned by
++ *  the CPU
++ */
++extern void tx_take_ownership(gmac_desc_list_info_t* desc_list);
 +
-+                              // Free the socket buffer
-+                              dev_kfree_skb(skb);
++/** Return the number of descriptors available for the CPU to fill with new
++ *  packet info */
++static inline int available_for_write(gmac_desc_list_info_t* desc_list)
++{
++    return desc_list->empty_count;
++}
 +
-+                              // No more RX descriptor ring entries to refill
-+                              break;
-+                      }
-+              }
++/** Return non-zero if there is a descriptor available with a packet with which
++ *  the GMAC DMA has finished */
++static inline int tx_available_for_read(
++      volatile gmac_desc_list_info_t *desc_list,
++      u32                            *status)
++{
++      if (!desc_list->full_count) {
++              return 0;
 +      }
 +
-+#ifndef CONFIG_HIPOX_VERSION_0X800
-+      if (likely(filled)) {
-+              // Issue a RX poll demand to restart RX descriptor processing and DFF
-+              // mode does not automatically restart descriptor processing after a
-+              // descriptor unavailable event
-+              dma_reg_write(priv, DMA_RX_POLL_REG, 0);
++      *status = (desc_list->base_ptr + desc_list->r_index)->status;
++
++      if (*status & (1UL << TDES0_OWN_BIT)) {
++              return 0;
 +      }
-+#endif // !CONFIG_HIPOX_VERSION_0X800
-+}
 +
-+static inline void set_phy_type_rgmii(void)
-+{
-+#ifndef CONFIG_HIPOX_VERSION_0X800
-+      // Use sysctrl to switch MAC link lines into either (G)MII or RGMII mode
-+      u32 reg_contents = readl(SYS_CTRL_GMAC_CTRL);
-+      reg_contents |= (1UL << SYS_CTRL_GMAC_RGMII);
-+    writel(reg_contents, SYS_CTRL_RSTEN_SET_CTRL);
-+#endif // !CONFIG_HIPOX_VERSION_0X800
++      return 1;
 +}
 +
-+static void initialise_phy(gmac_priv_t* priv)
++/**
++ * Return non-zero if there is a descriptor available with a packet with which
++ * the GMAC DMA has finished.
++ */
++static inline int rx_available_for_read(
++      volatile gmac_desc_list_info_t *desc_list,
++      u32                            *status)
 +{
-+      switch (priv->phy_type) {
-+              case PHY_TYPE_VITESSE_VSC8201XVZ:
-+                      {
-+                              // Allow s/w to override mode/duplex pin settings
-+                              u32 acsr = priv->mii.mdio_read(priv->netdev, priv->mii.phy_id, VSC8201_MII_ACSR);
-+
-+                              printk(KERN_INFO "%s: PHY is Vitesse VSC8201XVZ\n", priv->netdev->name);
-+                              acsr |= (1UL << VSC8201_MII_ACSR_MDPPS_BIT);
-+                              priv->mii.mdio_write(priv->netdev, priv->mii.phy_id, VSC8201_MII_ACSR, acsr);
-+                      }
-+                      break;
-+              case PHY_TYPE_REALTEK_RTL8211BGR:
-+                      printk(KERN_INFO "%s: PHY is Realtek RTL8211BGR\n", priv->netdev->name);
-+                      set_phy_type_rgmii();
-+                      break;
-+              case PHY_TYPE_LSI_ET1011C:
-+              case PHY_TYPE_LSI_ET1011C2:
-+                      {
-+                              u32 phy_reg;
++      u32 local_status;
 +
-+                              printk(KERN_INFO "%s: PHY is LSI ET1011C\n", priv->netdev->name);
++      if (!desc_list->full_count) {
++              return 0;
++      }
 +
-+                              // Configure clocks
-+                              phy_reg = priv->mii.mdio_read(priv->netdev, priv->mii.phy_id, ET1011C_MII_CONFIG);
-+                              phy_reg &= ~(((1UL << ET1011C_MII_CONFIG_IFMODESEL_NUM_BITS) - 1) << ET1011C_MII_CONFIG_IFMODESEL);
-+                              phy_reg |= (ET1011C_MII_CONFIG_IFMODESEL_GMII_MII << ET1011C_MII_CONFIG_IFMODESEL);
-+                              phy_reg |= ((1UL << ET1011C_MII_CONFIG_SYSCLKEN) |
-+                              (1UL << ET1011C_MII_CONFIG_TXCLKEN) |
-+                                                         (1UL << ET1011C_MII_CONFIG_TBI_RATESEL) |
-+                                                         (1UL << ET1011C_MII_CONFIG_CRS_TX_EN));
-+                              priv->mii.mdio_write(priv->netdev, priv->mii.phy_id, ET1011C_MII_CONFIG, phy_reg);
++      local_status = (desc_list->base_ptr + desc_list->r_index)->status;
 +
-+                              // Enable Tx/Rx LED
-+                              phy_reg = priv->mii.mdio_read(priv->netdev, priv->mii.phy_id, ET1011C_MII_LED2);
-+                              phy_reg &= ~(((1UL << ET1011C_MII_LED2_LED_NUM_BITS) - 1) << ET1011C_MII_LED2_LED_TXRX);
-+                              phy_reg |= (ET1011C_MII_LED2_LED_TXRX_ACTIVITY << ET1011C_MII_LED2_LED_TXRX);
-+                              priv->mii.mdio_write(priv->netdev, priv->mii.phy_id, ET1011C_MII_LED2, phy_reg);
-+                      }
-+                      break;
-+              case PHY_TYPE_ICPLUS_IP1001:
-+                      printk(KERN_INFO "%s: PHY is ICPlus 1001\n", priv->netdev->name);
-+                      break;
++    if (local_status & (1UL << RDES0_OWN_BIT)) {
++              return 0;
 +      }
-+}
-+
-+static struct kobj_type ktype_gmac_link_state = {
-+      .release = 0,
-+      .sysfs_ops = 0,
-+      .default_attrs = 0,
-+};
 +
-+static int gmac_link_state_hotplug_filter(struct kset* kset, struct kobject* kobj) {
-+      return get_ktype(kobj) == &ktype_gmac_link_state;
-+}
++      if (status) {
++              *status = local_status;
++      }
 +
-+static const char* gmac_link_state_hotplug_name(struct kset* kset, struct kobject* kobj) {
-+      return "gmac_link_state";
++    return 1;
 +}
 +
-+static struct kset_uevent_ops gmac_link_state_uevent_ops = {
-+      .filter = gmac_link_state_hotplug_filter,
-+      .name   = gmac_link_state_hotplug_name,
-+      .uevent = NULL,
-+};
-+
-+static int gmac_link_state_init_sysfs(gmac_priv_t* priv)
-+{
-+      int err = 0;
++typedef struct rx_frag_info {
++      struct page *page;
++    dma_addr_t      phys_adr;
++    u16             length;
++} rx_frag_info_t;
 +
-+      /* Prepare the sysfs interface for use */
-+      kobject_set_name(&priv->link_state_kset.kobj, "gmac_link_state");
-+      priv->link_state_kset.ktype = &ktype_gmac_link_state;
++/**
++ * Fill a RX descriptor and pass ownership to DMA engine
++ */
++extern int set_rx_descriptor(
++    gmac_priv_t    *priv,
++    rx_frag_info_t *frag_info);
 +
-+      err = subsystem_register(&priv->link_state_kset);
-+      if (err)
-+              return err;
++/**
++ * Extract data from the next available descriptor with which the GMAC DMA
++ * controller has finished.
++ * The caller indicates via the 'first_last' argument whether the first
++ * descriptor contributing to a packet is expected. The 'first_last' argument
++ * will be returned set to indicate whether the descriptor was the last
++ * contributing to a packet.
++ * If the 'status' argument is non-null it will have the status from the
++ * descriptor or'ed into it, thus enabling the compound status for all
++ * descriptors contributing to a packet to be built up
++ */
++extern int get_rx_descriptor(
++    gmac_priv_t    *priv,
++    int            *last,
++    u32            *status,
++    rx_frag_info_t *frag_info);
 +
-+      /* Setup hotplugging */
-+      priv->link_state_kset.uevent_ops = &gmac_link_state_uevent_ops;
++/**
++ * Fill in descriptors describing all fragments in a single Tx packet and pass
++ * ownership to the GMAC. The 'frag_info' argument points to an array describing
++ * each buffer that is to contribute to the transmitted packet. The 'frag_count'
++ * argument gives the number of elements in that array
++ */
++extern int set_tx_descriptor(
++    gmac_priv_t    *priv,
++    struct sk_buff *skb,
++    tx_frag_info_t *frag_info,
++    int             frag_count,
++    int             use_hw_csum);
 +
-+      /* Setup the heirarchy, the name will be set on detection */
-+      kobject_init(&priv->link_state_kobject);
-+      priv->link_state_kobject.kset = kset_get(&priv->link_state_kset);
-+      priv->link_state_kobject.parent = &priv->link_state_kset.kobj;
++/**
++ * Extract information about the TX packet transmitted the longest time ago.
++ * If the 'status' argument is non-null it will have the status from the
++ * descriptor or'ed into it.
++ */
++extern int get_tx_descriptor(
++    gmac_priv_t     *priv,
++    struct sk_buff **skb,
++    u32             *status,
++    tx_frag_info_t  *frag_info,
++    int             *buffer_owned); 
 +
-+      /* Build the sysfs entry */
-+      kobject_set_name(&priv->link_state_kobject, "gmac_link_state-1");
-+      return kobject_add(&priv->link_state_kobject);
++/**
++ * @param A u32 containing the status from a received frame's DMA descriptor
++ * @return An int which is non-zero if a valid received frame has no error
++ *         condititions flagged
++ */
++static inline int is_rx_valid(u32 status)
++{
++    return !(status & (1UL << RDES0_ES_BIT)) &&
++           !(status & (1UL << RDES0_IPC_BIT));
 +}
 +
-+static void work_handler(struct work_struct *ws) {
-+      gmac_priv_t *priv = container_of(ws, gmac_priv_t, link_state_change_work);
-+
-+      kobject_uevent(&priv->link_state_kobject, priv->link_state ? KOBJ_ONLINE : KOBJ_OFFLINE);
++static inline int is_rx_dribbling(u32 status)
++{
++    return status & (1UL << RDES0_DRE_BIT);
 +}
 +
-+static void link_state_change_callback(
-+      int   link_state,
-+      void *arg)
++static inline u32 get_rx_length(u32 status)
 +{
-+      gmac_priv_t* priv = (gmac_priv_t*)arg;
-+
-+      priv->link_state = link_state;
-+      schedule_work(&priv->link_state_change_work);
++    return (status >> RDES0_FL_BIT) & ((1UL << RX_DESC_STATUS_FL_NUM_BITS) - 1);
 +}
 +
-+static void start_watchdog_timer(gmac_priv_t* priv)
++static inline int is_rx_collision_error(u32 status)
 +{
-+    priv->watchdog_timer.expires = jiffies + WATCHDOG_TIMER_INTERVAL;
-+    priv->watchdog_timer_shutdown = 0;
-+    mod_timer(&priv->watchdog_timer, priv->watchdog_timer.expires);
++    return status & ((1UL << RDES0_OE_BIT) | (1UL << RDES0_LC_BIT));
 +}
 +
-+static void delete_watchdog_timer(gmac_priv_t* priv)
++static inline int is_rx_crc_error(u32 status)
 +{
-+    // Ensure link/PHY state watchdog timer won't be invoked again
-+    priv->watchdog_timer_shutdown = 1;
-+    del_timer_sync(&priv->watchdog_timer);
++    return status & (1UL << RDES0_CE_BIT);
 +}
 +
-+static inline int is_auto_negotiation_in_progress(gmac_priv_t* priv)
++static inline int is_rx_frame_error(u32 status)
 +{
-+    return !(phy_read(priv->netdev, priv->phy_addr, MII_BMSR) & BMSR_ANEGCOMPLETE);
++    return status & (1UL << RDES0_DE_BIT);
 +}
 +
-+static void watchdog_timer_action(unsigned long arg)
++static inline int is_rx_length_error(u32 status)
 +{
-+    typedef enum watchdog_state {
-+        WDS_IDLE,
-+        WDS_RESETTING,
-+        WDS_NEGOTIATING
-+    } watchdog_state_t;
-+
-+    static int state = WDS_IDLE;
-+
-+    gmac_priv_t* priv = (gmac_priv_t*)arg;
-+    unsigned long new_timeout = jiffies + WATCHDOG_TIMER_INTERVAL;
-+#ifndef ARMULATING
-+    int ready;
-+    int duplex_changed;
-+    int gigabit_changed;
-+    int pause_changed;
-+
-+      // Interpret the PHY/link state.
-+      if (priv->phy_force_negotiation || (state == WDS_RESETTING)) {
-+              mii_check_link(&priv->mii);
-+              ready = 0;
-+      } else {
-+              duplex_changed = mii_check_media_ex(&priv->mii, 1, priv->mii_init_media, &gigabit_changed, &pause_changed, link_state_change_callback, priv);
-+              priv->mii_init_media = 0;
-+              ready = netif_carrier_ok(priv->netdev);
-+      }
-+
-+    if (!ready) {
-+        if (priv->phy_force_negotiation) {
-+            if (netif_carrier_ok(priv->netdev)) {
-+                state = WDS_RESETTING;
-+            } else {
-+                state = WDS_IDLE;
-+            }
-+
-+            priv->phy_force_negotiation = 0;
-+        }
-+
-+        // May be a good idea to restart everything here, in an attempt to clear
-+        // out any fault conditions
-+        if ((state == WDS_NEGOTIATING) && is_auto_negotiation_in_progress(priv)) {
-+            new_timeout = jiffies + AUTO_NEG_INTERVAL;
-+        } else {
-+            switch (state) {
-+                case WDS_IDLE:
-+                    // Reset the PHY to get it into a known state
-+                    start_phy_reset(priv);
-+                    new_timeout = jiffies + START_RESET_INTERVAL;
-+                    state = WDS_RESETTING;
-+                    break;
-+                case WDS_RESETTING:
-+                    if (!is_phy_reset_complete(priv)) {
-+                        new_timeout = jiffies + RESET_INTERVAL;
-+                    } else {
-+                        // Force or auto-negotiate PHY mode
-+                        set_phy_negotiate_mode(priv->netdev);
-+
-+                        // Set PHY specfic features
-+                        initialise_phy(priv);
-+
-+                        state = WDS_NEGOTIATING;
-+                        new_timeout = jiffies + AUTO_NEG_INTERVAL;
-+                    }
-+                    break;
-+                default:
-+                    DBG(1, KERN_ERR "watchdog_timer_action() %s: Unexpected state\n", priv->netdev->name);
-+                    state = WDS_IDLE;
-+                    break;
-+            }
-+        }
-+    } else {
-+        state = WDS_IDLE;
-+        if (duplex_changed) {
-+            priv->mii.full_duplex ? mac_reg_set_mask(priv,   MAC_CONFIG_REG, (1UL << MAC_CONFIG_DM_BIT)) :
-+                                    mac_reg_clear_mask(priv, MAC_CONFIG_REG, (1UL << MAC_CONFIG_DM_BIT));
-+        }
-+
-+        if (gigabit_changed) {
-+            change_gig_mode(priv);
-+        }
-+
-+              if (pause_changed) {
-+                      change_pause_mode(priv);
-+              }
-+    }
-+#endif // !ARMULATING
++    return status & (1UL << RDES0_LE_BIT);
++}
 +
-+    // Re-trigger the timer, unless some other thread has requested it be stopped
-+    if (!priv->watchdog_timer_shutdown) {
-+        // Restart the timer
-+        mod_timer(&priv->watchdog_timer, new_timeout);
-+    }
++static inline int is_rx_csum_error(u32 status)
++{
++    return (status & (1UL << RDES0_IPC_BIT))
++#ifndef CONFIG_HIPOX_VERSION_0X800
++           || (status & (1UL << RDES0_PCE_BIT))
++#endif // !CONFIG_HIPOX_VERSION_0X800
++           ;
 +}
 +
-+static int inline is_ip_packet(unsigned short eth_protocol)
++static inline int is_rx_long_frame(u32 status)
 +{
-+    return (eth_protocol == ETH_P_IP)
-+#ifdef SUPPORT_IPV6
-+              || (eth_protocol == ETH_P_IPV6)
-+#endif // SUPPORT_IPV6
-+              ;
++    return status & (1UL << RDES0_VLAN_BIT);
 +}
 +
-+static int inline is_ipv4_packet(unsigned short eth_protocol)
++static inline int is_tx_valid(u32 status)
 +{
-+    return eth_protocol == ETH_P_IP;
++    return !(status & (1UL << TDES0_ES_BIT));
 +}
 +
-+#ifdef SUPPORT_IPV6
-+static int inline is_ipv6_packet(unsigned short eth_protocol)
++static inline int is_tx_collision_error(u32 status)
 +{
-+    return eth_protocol == ETH_P_IPV6;
++    return (status & (((1UL << TDES0_CC_NUM_BITS) - 1) << TDES0_CC_BIT)) >> TDES0_CC_BIT;
 +}
-+#endif // SUPPORT_IPV6
 +
-+static int inline is_hw_checksummable(unsigned short protocol)
++static inline int is_tx_aborted(u32 status)
 +{
-+    return (protocol == IPPROTO_TCP) || (protocol == IPPROTO_UDP)
-+#ifndef CONFIG_HIPOX_VERSION_0X800
-+           || (protocol == IPPROTO_ICMP)
-+#endif // !CONFIG_HIPOX_VERSION_0X800
-+           ;
++    return status & ((1UL << TDES0_LC_BIT) | (1UL << TDES0_EC_BIT));
 +}
 +
-+static u32 unmap_rx_page(
-+      gmac_priv_t *priv,
-+      dma_addr_t   phys_adr)
++static inline int is_tx_carrier_error(u32 status)
 +{
-+      u32 offset = phys_adr & ~PAGE_MASK;
-+      u32 next_offset = offset + priv->rx_buffer_size_;
-+      next_offset = SKB_DATA_ALIGN(next_offset);
-+      next_offset += NET_IP_ALIGN;
++    return status & ((1UL << TDES0_LOC_BIT) | (1UL << TDES0_NC_BIT));
++}
 +
-+      // If this is the last packet in a page
-+      if (next_offset > GMAC_ALLOC_SIZE) {
-+              // Release the DMA mapping for the page
-+              dma_unmap_page(0, phys_adr & PAGE_MASK, GMAC_ALLOC_SIZE, DMA_FROM_DEVICE);
-+      }
++static inline u16 max_descriptor_length(void) {
++      static const int GMAC_MAX_DESC_LEN = 2047;
 +
-+      return offset;
++      return GMAC_MAX_DESC_LEN;
 +}
++#endif  //  #if !defined(__GMAC_DESC_H__)
 +
-+#define FCS_LEN 4             // Ethernet CRC length
-+#ifdef CONFIG_HIPOX_VERSION_0X800
-+#define HW_CSUM_LEN 2 // The OX800 H/W appending partial csum length
-+#endif // CONFIG_HIPOX_VERSION_0X800
-+
-+static inline int get_desc_len(
-+      u32 desc_status,
-+      int last)
-+{
-+      int length = get_rx_length(desc_status);
+diff -Nurd linux-2.6.24.4/arch/arm/mach-hipox/gmac_ethtool.c linux-2.6.24/arch/arm/mach-hipox/gmac_ethtool.c
+--- linux-2.6.24.4/arch/arm/mach-hipox/gmac_ethtool.c  1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/mach-hipox/gmac_ethtool.c    2010-01-14 14:01:15.000000000 +0100
+@@ -0,0 +1,275 @@
++/*
++ * linux/arch/arm/mach-hipox/gmac_ethtool.c
++ *
++ * Copyright (C) 2005 Oxford Semiconductor Ltd
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++ 
++#include <asm/types.h>
++#include <linux/errno.h>
++#include <linux/ethtool.h>
++#include <linux/netdevice.h>
++#include <asm/io.h>
++#include <asm/arch/leon.h>
 +
-+      if (last) {
-+              length -= FCS_LEN;
-+#if defined(CONFIG_HIPOX_VERSION_0X800) && defined(USE_RX_CSUM)
-+          length -= HW_CSUM_LEN;
-+#endif // CONFIG_HIPOX_VERSION_0X800 && USE_RX_CSUM
-+      }
++//#define GMAC_DEBUG
++#undef GMAC_DEBUG
 +
-+      return length;
-+}
++#include "gmac.h"
++#include "gmac_desc.h"
 +
-+static int process_rx_packet_skb(gmac_priv_t *priv)
++static int get_settings(struct net_device* dev, struct ethtool_cmd* cmd)
 +{
-+      int             desc;
-+      int             last;
-+      u32             desc_status = 0;
-+      rx_frag_info_t  frag_info;
-+      int             packet_len;
-+      struct sk_buff *skb;
-+      int             valid;
-+      int             ip_summed;
-+
-+      desc = get_rx_descriptor(priv, &last, &desc_status, &frag_info);
-+      if (desc < 0) {
-+              return 0;
-+      }
++    gmac_priv_t* priv = (gmac_priv_t*)netdev_priv(dev);
++    unsigned long irq_flags;
++    int status;
 +
-+      // Release the DMA mapping for the received data
-+    dma_unmap_single(0, frag_info.phys_adr, frag_info.length, DMA_FROM_DEVICE);
++    spin_lock_irqsave(&priv->phy_lock, irq_flags);
++    status = mii_ethtool_gset(&priv->mii, cmd);
++    spin_unlock_irqrestore(&priv->phy_lock, irq_flags);
 +
-+      // Get the packet data length
-+      packet_len = get_desc_len(desc_status, last);
++    return status;
++}
 +
-+      // Get pointer to the SKB
-+      skb = (struct sk_buff*)frag_info.page;
++static int set_settings(struct net_device* dev, struct ethtool_cmd* cmd)
++{
++    gmac_priv_t* priv = (gmac_priv_t*)netdev_priv(dev);
++    unsigned long irq_flags;
++    int status;
 +
-+      // Is the packet entirely contained within the descriptors and without errors?
-+      valid = !(desc_status & (1UL << RDES0_ES_BIT));
++    spin_lock_irqsave(&priv->phy_lock, irq_flags);
++    status = mii_ethtool_sset(&priv->mii, cmd);
++    spin_unlock_irqrestore(&priv->phy_lock, irq_flags);
 +
-+      if (unlikely(!valid)) {
-+              goto not_valid_skb;
-+      }
++    return status;
++}
 +
-+      ip_summed = CHECKSUM_NONE;
++static void get_drvinfo(struct net_device* dev, struct ethtool_drvinfo* drvinfo)
++{
++    strncpy(drvinfo->driver,     "GMAC", 32);
++    strncpy(drvinfo->version,    "1.0", 32);
++    strncpy(drvinfo->fw_version, "1.0", 32);    // Version of CoPro s/w
++    strncpy(drvinfo->bus_info,   "AMBA", 32);
++}
 +
-+#ifdef USE_RX_CSUM
-+      // Has the h/w flagged an IP header checksum failure?
-+      valid = !(desc_status & (1UL << RDES0_IPC_BIT));
++static int nway_reset(struct net_device* dev)
++{
++    gmac_priv_t* priv = (gmac_priv_t*)netdev_priv(dev);
++    unsigned long irq_flags;
++    int status;
 +
-+      if (likely(valid)) {
-+              // Determine whether Ethernet frame contains an IP packet -
-+              // only bother with Ethernet II frames, but do cope with
-+              // 802.1Q VLAN tag presence
-+              int vlan_offset = 0;
-+              unsigned short eth_protocol = ntohs(((struct ethhdr*)skb->data)->h_proto);
-+              int is_ip = is_ip_packet(eth_protocol);
++    spin_lock_irqsave(&priv->phy_lock, irq_flags);
++    status = mii_nway_restart(&priv->mii);
++    spin_unlock_irqrestore(&priv->phy_lock, irq_flags);
 +
-+              if (!is_ip) {
-+                      // Check for VLAN tag
-+                      if (eth_protocol == ETH_P_8021Q) {
-+                              // Extract the contained protocol type from after
-+                              // the VLAN tag
-+                              eth_protocol = ntohs(*(unsigned short*)(skb->data + ETH_HLEN));
-+                              is_ip = is_ip_packet(eth_protocol);
++    return status;
++}
 +
-+                              // Adjustment required to skip the VLAN stuff and
-+                              // get to the IP header
-+                              vlan_offset = 4;
-+                      }
-+              }
++static u32 get_msglevel(struct net_device* dev)
++{
++    return ((gmac_priv_t*)netdev_priv(dev))->msg_level;
++}
 +
-+              // Only offload checksum calculation for IP packets
-+              if (is_ip) {
-+#ifdef CONFIG_HIPOX_VERSION_0X800
-+                      u16 payload_length = 0;
-+#endif // CONFIG_HIPOX_VERSION_0X800
-+                      struct iphdr* ipv4_header = 0;
++static void set_msglevel(struct net_device* dev, u32 data)
++{
++    ((gmac_priv_t*)netdev_priv(dev))->msg_level = data;
++}
 +
-+#ifndef CONFIG_HIPOX_VERSION_0X800
-+                      if (unlikely(desc_status & (1UL << RDES0_PCE_BIT))) {
-+                              valid = 0;
-+                      } else
-+#endif // !CONFIG_HIPOX_VERSION_0X800
-+                      if (is_ipv4_packet(eth_protocol)) {
-+                              ipv4_header = (struct iphdr*)(skb->data + ETH_HLEN + vlan_offset);
++static u32 get_rx_csum(struct net_device* dev)
++{
++#ifdef USE_RX_CSUM
++      return 1;
++#else
++      return 0;
++#endif
++}
 +
-+                              // H/W can only checksum non-fragmented IP packets
-+                              if (!(ipv4_header->frag_off & htons(IP_MF | IP_OFFSET))) {
-+#ifdef CONFIG_HIPOX_VERSION_0X800
-+                                      switch (ipv4_header->protocol) {
-+                                              case IPPROTO_TCP:
-+                                                      // Compute TCP pseudo-header checksum
-+                                                      payload_length = ntohs(ipv4_header->tot_len) - (ipv4_header->ihl*4);
-+                                                      break;
-+                                              case IPPROTO_UDP:
-+                                                      {
-+                                                              struct udphdr* udp_header = (struct udphdr*)((u8*)ipv4_header + (ipv4_header->ihl*4));
-+                                                              payload_length = ntohs(udp_header->len);
-+                                                      }
-+                                                      break;
-+                                              default:
-+                                                      // Not supporting any other than TCP/UDP
-+                                                      break;
-+                                      }
-+#else // CONFIG_HIPOX_VERSION_0X800
-+                              if (is_hw_checksummable(ipv4_header->protocol)) {
-+                                      ip_summed = CHECKSUM_UNNECESSARY;
-+                              }
-+#endif // CONFIG_HIPOX_VERSION_0X800
-+                              }
-+                      }
-+#ifndef CONFIG_HIPOX_VERSION_0X800
-+                       else {
-+#ifdef SUPPORT_IPV6
-+                              struct ipv6hdr* ipv6_header = (struct ipv6hdr*)(skb->data + ETH_HLEN + vlan_offset);
++static int set_rx_csum(struct net_device* dev, u32 data)
++{
++    return 0;
++}
 +
-+                              if (is_hw_checksummable(ipv6_header->nexthdr)) {
-+                                      ip_summed = CHECKSUM_UNNECESSARY;
-+                              }
-+#endif // SUPPORT_IPV6
-+                      }
-+#endif // !CONFIG_HIPOX_VERSION_0X800
++static int get_regs_len(struct net_device* dev)
++{
++    return 0;
++}
 +
-+#ifdef CONFIG_HIPOX_VERSION_0X800
-+                      if (payload_length) {
-+                              // Get the hardware generated payload checksum from
-+                              // the end of the received packet, reverse the 1's
-+                              // complement operation that the h/w applies and add
-+                              // to the pseudo-header checksum, in network order
-+                              u16 hw_csum = ~(*(u16*)(skb->data + packet_len + FCS_LEN));
++static void get_regs(struct net_device* dev, struct ethtool_regs* regs, void *p)
++{
++    gmac_priv_t   *priv = (gmac_priv_t*)netdev_priv(dev);
++    unsigned long  irq_state;
++      u32            status;
 +
-+                              // Calculate checksum of pseudo header and payload
-+                              if (csum_tcpudp_magic(
-+                                              ipv4_header->saddr,
-+                                              ipv4_header->daddr,
-+                                              payload_length,
-+                                              ipv4_header->protocol,
-+                                              hw_csum)) {
-+                                      // Bad checksum, so indicate in descriptor status
-+                                      desc_status |= (1UL << RDES0_IPC_BIT);
-+                                      valid = 0;
-+                              } else {
-+                                      ip_summed = CHECKSUM_UNNECESSARY;
-+                              }
-+                      }
-+#endif // CONFIG_HIPOX_VERSION_0X800
-+              }
-+      }
++    printk("RX ring info:\n");
++    printk("  num_descriptors     = %d\n", priv->rx_gmac_desc_list_info.num_descriptors);
++    printk("  empty_count         = %d\n", priv->rx_gmac_desc_list_info.empty_count);
++    printk("  full_count          = %d\n", priv->rx_gmac_desc_list_info.full_count);
++    printk("  r_index             = %d\n", priv->rx_gmac_desc_list_info.r_index);
++    printk("  w_index             = %d\n", priv->rx_gmac_desc_list_info.w_index);
++    printk("  available_for_write = %d\n", available_for_write(&priv->rx_gmac_desc_list_info));
++    printk("  available_for_read    %s\n", rx_available_for_read(&priv->rx_gmac_desc_list_info, 0) ? "yes" :"no");
 +
-+      if (unlikely(!valid)) {
-+              goto not_valid_skb;
-+      }
-+#endif // USE_RX_CSUM
++    spin_lock_irqsave(&priv->tx_spinlock_, irq_state);
++    printk("TX ring info:\n");
++    printk("  num_descriptors     = %d\n", priv->tx_gmac_desc_list_info.num_descriptors);
++    printk("  empty_count         = %d\n", priv->tx_gmac_desc_list_info.empty_count);
++    printk("  full_count          = %d\n", priv->tx_gmac_desc_list_info.full_count);
++    printk("  r_index             = %d\n", priv->tx_gmac_desc_list_info.r_index);
++    printk("  w_index             = %d\n", priv->tx_gmac_desc_list_info.w_index);
++    printk("  available_for_write = %d\n", available_for_write(&priv->tx_gmac_desc_list_info));
++    printk("  available_for_read    %s\n", tx_available_for_read(&priv->tx_gmac_desc_list_info, &status) ? "yes" : "no");
++    spin_unlock_irqrestore(&priv->tx_spinlock_, irq_state);
++}
 +
-+      // Increase the skb's data pointer to account for the RX packet that has
-+      // been DMAed into it
-+      skb_put(skb, packet_len);
++static void get_wol(struct net_device* dev, struct ethtool_wolinfo* wol_info)
++{
++}
 +
-+      // Set the device for the skb
-+      skb->dev = priv->netdev;
++static int set_wol(struct net_device* dev, struct ethtool_wolinfo* wol_info)
++{
++    return -EINVAL;
++}
 +
-+      // Set packet protocol
-+      skb->protocol = eth_type_trans(skb, priv->netdev);
++static int get_coalesce(struct net_device* dev, struct ethtool_coalesce *ethtool_coalesce)
++{
++#ifdef CONFIG_LEON_COPRO
++    gmac_priv_t* priv = (gmac_priv_t*)netdev_priv(dev);
 +
-+      // Record whether h/w checksumed the packet
-+      skb->ip_summed = ip_summed;
++    if (priv->copro_params_.rx_mitigation_) {
++        ethtool_coalesce->rx_max_coalesced_frames = priv->copro_params_.rx_mitigation_frames_;
++        ethtool_coalesce->rx_coalesce_usecs       = priv->copro_params_.rx_mitigation_usec_;
++printk("get_coalesce() %u packets, %u usec\n", ethtool_coalesce->rx_max_coalesced_frames, ethtool_coalesce->rx_coalesce_usecs);
++    }
++#endif // CONFIG_LEON_COPRO
++   return 0;
++}
 +
-+      // Send the packet up the network stack
-+      netif_receive_skb(skb);
++static int set_coalesce(struct net_device* dev, struct ethtool_coalesce *ethtool_coalesce)
++{
++#ifdef CONFIG_LEON_COPRO
++    gmac_priv_t* priv = (gmac_priv_t*)netdev_priv(dev);
 +
-+      // Update receive statistics
-+      priv->netdev->last_rx = jiffies;
-+      ++priv->stats.rx_packets;
-+      priv->stats.rx_bytes += packet_len;
++    if (priv->copro_params_.rx_mitigation_) {
++printk("set_coalesce() %u packets, %u usec\n", ethtool_coalesce->rx_max_coalesced_frames, ethtool_coalesce->rx_coalesce_usecs);
++        priv->copro_params_.rx_mitigation_frames_ = ethtool_coalesce->rx_max_coalesced_frames;
++        priv->copro_params_.rx_mitigation_usec_   = ethtool_coalesce->rx_coalesce_usecs;
 +
-+      return 1;
++        // Only attempt to write to uncached/unbuffered shared parameter storage
++        // if CoPro is started and thus storage has been allocated
++        if (priv->shared_copro_params_) {
++            // Fill the CoPro parameter block
++            memcpy(priv->shared_copro_params_, &priv->copro_params_, sizeof(copro_params_t));
++        }
 +
-+not_valid_skb:
-+      dev_kfree_skb(skb);
++        // Make sure the CoPro parameter block updates have made it to memory (which
++        // is uncached/unbuffered, so just compiler issues to overcome)
++        wmb();
 +
-+      DBG(2, KERN_WARNING "process_rx_packet() %s: Received packet has bad desc_status = 0x%08x\n", priv->netdev->name, desc_status);
++        spin_lock(&priv->cmd_que_lock_);
++        cmd_que_queue_cmd(&priv->cmd_queue_, GMAC_CMD_UPDATE_PARAMS, 0, 0);
++        spin_unlock(&priv->cmd_que_lock_);
 +
-+      // Update receive statistics from the descriptor status
-+      if (is_rx_collision_error(desc_status)) {
-+              DBG(20, KERN_INFO "process_rx_packet() %s: Collision (0x%08x:%u bytes)\n", priv->netdev->name, desc_status, desc_len);
-+              ++priv->stats.collisions;
-+      }
-+      if (is_rx_crc_error(desc_status)) {
-+              DBG(20, KERN_INFO "process_rx_packet() %s: CRC error (0x%08x:%u bytes)\n", priv->netdev->name, desc_status, desc_len);
-+              ++priv->stats.rx_crc_errors;
-+              ++priv->stats.rx_errors;
-+      }
-+      if (is_rx_frame_error(desc_status)) {
-+              DBG(20, KERN_INFO "process_rx_packet() %s: frame error (0x%08x:%u bytes)\n", priv->netdev->name, desc_status, desc_len);
-+              ++priv->stats.rx_frame_errors;
-+              ++priv->stats.rx_errors;
-+      }
-+      if (is_rx_length_error(desc_status)) {
-+              DBG(20, KERN_INFO "process_rx_packet() %s: Length error (0x%08x:%u bytes)\n", priv->netdev->name, desc_status, desc_len);
-+              ++priv->stats.rx_length_errors;
-+              ++priv->stats.rx_errors;
-+      }
-+      if (is_rx_csum_error(desc_status)) {
-+              DBG(20, KERN_INFO "process_rx_packet() %s: Checksum error (0x%08x:%u bytes)\n", priv->netdev->name, desc_status, desc_len);
-+              ++priv->stats.rx_frame_errors;
-+              ++priv->stats.rx_errors;
-+      }
++        // Interrupt the CoPro so it sees the new command
++        writel(1UL << COPRO_SEM_INT_CMD, SYS_CTRL_SEMA_SET_CTRL);
++    }
++#endif // CONFIG_LEON_COPRO
 +
-+      return 0;
++    return 0;
 +}
 +
-+static int process_rx_packet(gmac_priv_t *priv)
++static void get_ringparam(struct net_device* dev, struct ethtool_ringparam *ethtool_ringparam)
 +{
-+      struct sk_buff *skb = NULL;
-+      int             last;
-+      u32             desc_status;
-+      rx_frag_info_t  frag_info;
-+      int             desc;
-+      u32             offset;
-+      int             desc_len;
-+      unsigned char  *packet;
-+      int             valid;
-+      int             desc_used = 0;
-+      int             hlen = 0;
-+      int             partial_len = 0;
-+      int             first = 1;
-+
-+      // Check that there is at least one Rx descriptor available. Cache the
-+      // descriptor information so we don't have to touch the uncached/unbuffered
-+      // descriptor memory more than necessary when we come to use that descriptor
-+      if (!rx_available_for_read(&priv->rx_gmac_desc_list_info, &desc_status)) {
-+              return 0;
-+      }
-+
-+      // Attempt to allocate an skb before we change anything on the Rx descriptor ring
-+      skb = dev_alloc_skb(GMAC_HLEN + NET_IP_ALIGN);
-+      if (unlikely(skb == NULL)) {
-+              return 0;
-+      }
-+
-+      // Align IP header start in header storage
-+      skb_reserve(skb, NET_IP_ALIGN);
-+
-+      // Process all descriptors associated with the packet
-+      while (1) {
-+              int prev_len;
++}
 +
-+              // First call to get_rx_descriptor() will use the status read from the
-+              // first descriptor by the call to rx_available_for_read() above
-+              while ((desc = get_rx_descriptor(priv, &last, &desc_status, &frag_info)) < 0) {
-+                      // We are part way through processing a multi-descriptor packet
-+                      // and the GMAC hasn't finished with the next descriptor for the
-+                      // packet yet, so have to poll until it becomes available
-+                      desc_status = 0;
-+                      udelay(1);
-+              }
++static int set_ringparam(struct net_device* dev, struct ethtool_ringparam *ethtool_ringparam)
++{
++    return -EINVAL;
++}
 +
-+              // We've consumed a descriptor
-+              ++desc_used;
++static void get_pauseparam(struct net_device* dev, struct ethtool_pauseparam* ethtool_pauseparam)
++{
++}
 +
-+              if (!frag_info.page) {
-+                      panic("process_rx_packet() %s: Found RX descriptor without attached page\n", priv->netdev->name);
-+              }
++static int set_pauseparam(struct net_device* dev, struct ethtool_pauseparam* ethtool_pauseparam)
++{
++    return -EINVAL;
++}
 +
-+              // If this is the last packet in the page, release the DMA mapping
-+              offset = unmap_rx_page(priv, frag_info.phys_adr);
-+              if (!first) {
-+                      // The buffer adr of descriptors associate with middle or last
-+                      // parts of a packet have ls 2 bits of buffer adr ignored by GMAC DMA
-+                      offset &= ~0x3;
-+              }
++static int self_test_count(struct net_device* dev)
++{
++    return -EINVAL;
++}
 +
-+              // Get the length of the packet excluding CRC, h/w csum etc.
-+              prev_len = partial_len;
-+              partial_len = get_desc_len(desc_status, last);
-+              desc_len = partial_len - prev_len;
++static void self_test(struct net_device* dev, struct ethtool_test* ethtool_test, u64 *data)
++{
++}
 +
-+              // Get a pointer to the start of the packet data received into page
-+              packet = page_address(frag_info.page) + offset;
++static void get_strings(struct net_device* dev, u32 stringset, u8 *data)
++{
++}
 +
-+              // Is the packet entirely contained within the desciptors and without errors?
-+              valid = !(desc_status & (1UL << RDES0_ES_BIT));
++static int phys_id(struct net_device* dev, u32 data)
++{
++    return -EINVAL;
++}
 +
-+              if (unlikely(!valid)) {
-+                      goto not_valid;
-+              }
++static int get_stats_count(struct net_device* dev)
++{
++    return -EINVAL;
++}
 +
-+              if (first) {
-+                      // Store headers in skb buffer
-+                      hlen = min(GMAC_HLEN, desc_len);
++static void get_ethtool_stats(struct net_device* dev, struct ethtool_stats* ethtool_stats, u64 *data)
++{
++}
 +
-+                      // Copy header into skb buffer
-+                      memcpy(skb->data, packet, hlen);
-+                      skb->tail += hlen;
++static struct ethtool_ops ethtool_ops = {
++    .get_settings      = get_settings,
++    .set_settings      = set_settings,
++    .get_drvinfo       = get_drvinfo,
++    .get_regs_len      = get_regs_len,
++    .get_regs          = get_regs,
++    .get_wol           = get_wol,
++    .set_wol           = set_wol,
++    .get_msglevel      = get_msglevel,
++    .set_msglevel      = set_msglevel,
++    .nway_reset        = nway_reset,
++    .get_link          = ethtool_op_get_link,
++    .get_coalesce      = get_coalesce,
++    .set_coalesce      = set_coalesce,
++    .get_ringparam     = get_ringparam,
++    .set_ringparam     = set_ringparam,
++    .get_pauseparam    = get_pauseparam,
++    .set_pauseparam    = set_pauseparam,
++    .get_rx_csum       = get_rx_csum,
++    .set_rx_csum       = set_rx_csum,
++    .get_tx_csum       = ethtool_op_get_tx_csum,
++    .set_tx_csum       = ethtool_op_set_tx_csum,
++    .get_sg            = ethtool_op_get_sg,
++    .set_sg            = ethtool_op_set_sg,
++    .get_tso           = ethtool_op_get_tso,
++    .set_tso           = ethtool_op_set_tso,
++    .self_test_count   = self_test_count,
++    .self_test         = self_test,
++    .get_strings       = get_strings,
++    .phys_id           = phys_id,
++    .get_stats_count   = get_stats_count,
++    .get_ethtool_stats = get_ethtool_stats
++};
 +
-+                      if (desc_len > hlen) {
-+                              // Point skb frags array at remaining packet data in pages
-+                              skb_shinfo(skb)->nr_frags = 1;
-+                              skb_shinfo(skb)->frags[0].page = frag_info.page;
-+                              skb_shinfo(skb)->frags[0].page_offset = offset + hlen;
-+                              skb_shinfo(skb)->frags[0].size = desc_len - hlen;
-+                      } else {
-+                              // Entire packet now in skb buffer so don't require page anymore
-+                              put_page(frag_info.page);
-+                      }
++void set_ethtool_ops(struct net_device *netdev)
++{
++    SET_ETHTOOL_OPS(netdev, &ethtool_ops);
++}
+diff -Nurd linux-2.6.24.4/arch/arm/mach-hipox/gmac_ethtool.h linux-2.6.24/arch/arm/mach-hipox/gmac_ethtool.h
+--- linux-2.6.24.4/arch/arm/mach-hipox/gmac_ethtool.h  1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/mach-hipox/gmac_ethtool.h    2010-01-14 14:01:15.000000000 +0100
+@@ -0,0 +1,26 @@
++/*
++ * linux/arch/arm/mach-hipox/gmac_ethtool.h
++ *
++ * Copyright (C) 2005 Oxford Semiconductor Ltd
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++#if !defined(__GMAC_ETHTOOL_H__)
++#define __GMAC_ETHTOOL_H__
 +
-+                      first = 0;
-+              } else {
-+                      // Store intermediate descriptor data into packet
-+                      int frag_index = skb_shinfo(skb)->nr_frags;
-+                      skb_shinfo(skb)->frags[frag_index].page = frag_info.page;
-+                      skb_shinfo(skb)->frags[frag_index].page_offset = offset;
-+                      skb_shinfo(skb)->frags[frag_index].size = desc_len;
-+                      ++skb_shinfo(skb)->nr_frags;
-+              }
++extern void set_ethtool_ops(struct net_device *netdev);
 +
-+              if (last) {
-+                      int ip_summed = CHECKSUM_NONE;
++#endif        //  #if !defined(__GMAC_ETHTOOL_H__)
 +
-+                      // Update total packet length skb metadata
-+                      skb->len = partial_len;
-+                      skb->data_len = skb->len - hlen;
-+                      skb->truesize = skb->len + sizeof(struct sk_buff);
+diff -Nurd linux-2.6.24.4/arch/arm/mach-hipox/gmac.h linux-2.6.24/arch/arm/mach-hipox/gmac.h
+--- linux-2.6.24.4/arch/arm/mach-hipox/gmac.h  1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/mach-hipox/gmac.h    2010-01-14 14:01:15.000000000 +0100
+@@ -0,0 +1,194 @@
++/*
++ * linux/arch/arm/mach-hipox/gmac.h
++ *
++ * Copyright (C) 2005 Oxford Semiconductor Ltd
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++#if !defined(__GMAC_H__)
++#define __GMAC_H__
 +
-+#ifdef USE_RX_CSUM
-+                      // Has the h/w flagged an IP header checksum failure?
-+                      valid = !(desc_status & (1UL << RDES0_IPC_BIT));
++#include <asm/semaphore.h>
++#include <asm/types.h>
++#include <linux/mii.h>
++#include <linux/netdevice.h>
++#include <linux/spinlock.h>
++#include <linux/workqueue.h>
++#include <linux/list.h>
++#include <linux/ethtool.h>
++#include <linux/kobject.h>
++#include <asm/arch/desc_alloc.h>
++#include <asm/arch/dma.h>
++#ifdef CONFIG_LEON_COPRO
++#include <asm/arch/leon.h>
++#include "gmac_offload.h"
++#endif // CONFIG_LEON_COPRO
 +
-+                      // Are we offloading RX checksuming?
-+                      if (likely(valid)) {
-+                              // Determine whether Ethernet frame contains an IP packet -
-+                              // only bother with Ethernet II frames, but do cope with
-+                              // 802.1Q VLAN tag presence
-+                              int vlan_offset = 0;
-+                              unsigned short eth_protocol = ntohs(((struct ethhdr*)skb->data)->h_proto);
-+                              int is_ip = is_ip_packet(eth_protocol);
++#ifdef GMAC_DEBUG
++#define DBG(n, args...)\
++    do {\
++        if ((n) <= priv->msg_level)\
++            printk(args);\
++    } while (0)
++#else
++#define DBG(n, args...)   do { } while(0)
++#endif
 +
-+                              if (!is_ip) {
-+                                      // Check for VLAN tag
-+                                      if (eth_protocol == ETH_P_8021Q) {
-+                                              // Extract the contained protocol type from after
-+                                              // the VLAN tag
-+                                              eth_protocol = ntohs(*(unsigned short*)(skb->data + ETH_HLEN));
-+                                              is_ip = is_ip_packet(eth_protocol);
++#define MS_TO_JIFFIES(x) (((x) < (1000/(HZ))) ? 1 : (x) * (HZ) / 1000)
 +
-+                                              // Adjustment required to skip the VLAN stuff and
-+                                              // get to the IP header
-+                                              vlan_offset = 4;
-+                                      }
-+                              }
++#define USE_RX_CSUM
++//#define ARMULATING
 +
-+                              // Only offload checksum calculation for IP packets
-+                              if (is_ip) {
-+#ifdef CONFIG_HIPOX_VERSION_0X800
-+                                      u16 payload_length = 0;
-+#endif // CONFIG_HIPOX_VERSION_0X800
-+                                      struct iphdr* ipv4_header = 0;
++typedef struct gmac_desc_list_info {
++    volatile gmac_dma_desc_t *base_ptr;
++    gmac_dma_desc_t          *shadow_ptr;
++    int                       num_descriptors;
++    int                       empty_count;
++    int                       full_count;
++    int                       r_index;
++    int                       w_index;
++} gmac_desc_list_info_t;
 +
-+#ifndef CONFIG_HIPOX_VERSION_0X800
-+                                      if (unlikely(desc_status & (1UL << RDES0_PCE_BIT))) {
-+                                              valid = 0;
-+                                      } else
-+#endif // !CONFIG_HIPOX_VERSION_0X800
-+                                      if (is_ipv4_packet(eth_protocol)) {
-+                                              ipv4_header = (struct iphdr*)(skb->data + ETH_HLEN + vlan_offset);
++#ifdef CONFIG_LEON_COPRO
++typedef struct copro_params {
++    u32 cmd_que_head_;
++    u32 cmd_que_tail_;
++    u32 fwd_intrs_mailbox_;
++    u32 tx_que_head_;
++    u32 tx_que_tail_;
++    u32 free_start_;
++    u32 mtu_;
++    u32 rx_mitigation_;
++    u32 rx_mitigation_frames_;
++    u32 rx_mitigation_usec_;
++} __attribute ((aligned(4),packed)) copro_params_t;
++#endif // CONFIG_LEON_COPRO
 +
-+                                              // H/W can only checksum non-fragmented IP packets
-+                                              if (!(ipv4_header->frag_off & htons(IP_MF | IP_OFFSET))) {
-+#ifdef CONFIG_HIPOX_VERSION_0X800
-+                                                      switch (ipv4_header->protocol) {
-+                                                              case IPPROTO_TCP:
-+                                                                      // Compute TCP pseudo-header checksum
-+                                                                      payload_length = ntohs(ipv4_header->tot_len) - (ipv4_header->ihl*4);
-+                                                                      break;
-+                                                              case IPPROTO_UDP:
-+                                                                      {
-+                                                                              struct udphdr* udp_header = (struct udphdr*)((u8*)ipv4_header + (ipv4_header->ihl*4));
-+                                                                              payload_length = ntohs(udp_header->len);
-+                                                                      }
-+                                                                      break;
-+                                                              default:
-+                                                                      // Not supporting any other than TCP/UDP
-+                                                                      break;
-+                                                      }
-+#else // CONFIG_HIPOX_VERSION_0X800
-+                                              if (is_hw_checksummable(ipv4_header->protocol)) {
-+                                                      ip_summed = CHECKSUM_UNNECESSARY;
-+                                              }
-+#endif // CONFIG_HIPOX_VERSION_0X800
-+                                              }
-+                                      }
-+#ifndef CONFIG_HIPOX_VERSION_0X800
-+                                       else {
-+#ifdef SUPPORT_IPV6
-+                                              struct ipv6hdr* ipv6_header = (struct ipv6hdr*)(skb->data + ETH_HLEN + vlan_offset);
++typedef struct tx_frag_info {
++    dma_addr_t  phys_adr;
++    u16         length;
++} tx_frag_info_t;
 +
-+                                              if (is_hw_checksummable(ipv6_header->nexthdr)) {
-+                                                      ip_summed = CHECKSUM_UNNECESSARY;
-+                                              }
-+#endif // SUPPORT_IPV6
-+                                      }
-+#endif // !CONFIG_HIPOX_VERSION_0X800
++// Private data structure for the GMAC driver
++typedef struct gmac_priv {
++    /** Base address of GMAC MAC registers */
++    u32                       macBase;
++    /** Base address of GMAC DMA registers */
++    u32                       dmaBase;
 +
-+#ifdef CONFIG_HIPOX_VERSION_0X800
-+                                      if (payload_length) {
-+                                              // Get the hardware generated payload checksum from
-+                                              // the end of the received packet, reverse the 1's
-+                                              // complement operation that the h/w applies and add
-+                                              // to the pseudo-header checksum, in network order
-+                                              u16 hw_csum = ~(*(u16*)(packet + desc_len + FCS_LEN));
++    struct net_device*        netdev;
 +
-+                                              // Calculate checksum of pseudo header and payload
-+                                              if (csum_tcpudp_magic(
-+                                                              ipv4_header->saddr,
-+                                                              ipv4_header->daddr,
-+                                                              payload_length,
-+                                                              ipv4_header->protocol,
-+                                                              hw_csum)) {
-+                                                      // Bad checksum, so indicate in descriptor status
-+                                                      desc_status |= (1UL << RDES0_IPC_BIT);
-+                                                      valid = 0;
-+                                              } else {
-+                                                      ip_summed = CHECKSUM_UNNECESSARY;
-+                                              }
-+                                      }
-+#endif // CONFIG_HIPOX_VERSION_0X800
-+                              }
-+                      }
++    struct net_device_stats   stats;
 +
-+                      if (unlikely(!valid)) {
-+                              goto not_valid;
-+                      }
-+#endif // USE_RX_CSUM
++    u32                       msg_level;
++    
++    /** Whether we own an IRQ */
++    int                       have_irq;
 +
-+                      // Initialise other required skb header fields
-+                      skb->dev = priv->netdev;
-+                      skb->protocol = eth_type_trans(skb, priv->netdev);
++    /** Pointer to outstanding tx packet that has not yet been queued due to
++     *  lack of descriptors */
++    struct sk_buff           *tx_pending_skb;
++    tx_frag_info_t            tx_pending_fragments[18];
++    int                       tx_pending_fragment_count;
 +
-+                      // Record whether h/w checksumed the packet
-+                      skb->ip_summed = ip_summed;
++    /** DMA consistent physical address of outstanding tx packet */
++    dma_addr_t                tx_pending_dma_addr;
++    unsigned long             tx_pending_length;
 +
-+                      // Send the skb up the network stack
-+                      netif_receive_skb(skb);
++    /** To synchronise ISR and thread TX activities' access to private data */
++    spinlock_t                tx_spinlock_;
 +
-+                      // Update receive statistics
-+                      priv->netdev->last_rx = jiffies;
-+                      ++priv->stats.rx_packets;
-+                      priv->stats.rx_bytes += partial_len;
++    /** To synchronise access to the PHY */
++    spinlock_t                phy_lock;
 +
-+                      break;
-+              }
++    /** The timer for NAPI polling when out of memory when trying to fill RX
++     *  descriptor ring */
 +
-+              // Want next call to get_rx_descriptor() to read status from descriptor
-+              desc_status = 0;
-+      }
-+    return desc_used;
++    /** PHY related info */
++    struct mii_if_info        mii;
++    struct ethtool_cmd        ethtool_cmd;
++      struct ethtool_pauseparam ethtool_pauseparam;
++    u32                       phy_addr;
++    u32                       phy_type;
++    int                       gmii_csr_clk_range;
 +
-+not_valid:
-+      if (!skb_shinfo(skb)->nr_frags) {
-+              // Free the page as it wasn't attached to the skb
-+              put_page(frag_info.page);
-+      }
++    /** Periodic timer to check link status etc */
++    struct timer_list         watchdog_timer;
++    volatile int              watchdog_timer_shutdown;
 +
-+      dev_kfree_skb(skb);
++    /** The number of descriptors in the gmac_dma_desc_t array holding both the TX and
++     *  RX descriptors. The TX descriptors reside at the start of the array */
++    unsigned                  total_num_descriptors;
++    /** The CPU accessible virtual address of the start of the descriptor array */
++    gmac_dma_desc_t*          desc_vaddr;
++    /** The hardware accessible physical address of the start of the descriptor array */
++    dma_addr_t                desc_dma_addr;
 +
-+      DBG(2, KERN_WARNING "process_rx_packet() %s: Received packet has bad desc_status = 0x%08x\n", priv->netdev->name, desc_status);
++    /** Descriptor list management */
++    gmac_desc_list_info_t     tx_gmac_desc_list_info;
++    gmac_desc_list_info_t     rx_gmac_desc_list_info;
++    
++    /** Record of disabling RX overflow interrupts */
++    unsigned                  rx_overflow_ints_disabled;
 +
-+      // Update receive statistics from the descriptor status
-+      if (is_rx_collision_error(desc_status)) {
-+              DBG(20, KERN_INFO "process_rx_packet() %s: Collision (0x%08x:%u bytes)\n", priv->netdev->name, desc_status, desc_len);
-+              ++priv->stats.collisions;
-+      }
-+      if (is_rx_crc_error(desc_status)) {
-+              DBG(20, KERN_INFO "process_rx_packet() %s: CRC error (0x%08x:%u bytes)\n", priv->netdev->name, desc_status, desc_len);
-+              ++priv->stats.rx_crc_errors;
-+              ++priv->stats.rx_errors;
-+      }
-+      if (is_rx_frame_error(desc_status)) {
-+              DBG(20, KERN_INFO "process_rx_packet() %s: frame error (0x%08x:%u bytes)\n", priv->netdev->name, desc_status, desc_len);
-+              ++priv->stats.rx_frame_errors;
-+              ++priv->stats.rx_errors;
-+      }
-+      if (is_rx_length_error(desc_status)) {
-+              DBG(20, KERN_INFO "process_rx_packet() %s: Length error (0x%08x:%u bytes)\n", priv->netdev->name, desc_status, desc_len);
-+              ++priv->stats.rx_length_errors;
-+              ++priv->stats.rx_errors;
-+      }
-+      if (is_rx_csum_error(desc_status)) {
-+              DBG(20, KERN_INFO "process_rx_packet() %s: Checksum error (0x%08x:%u bytes)\n", priv->netdev->name, desc_status, desc_len);
-+              ++priv->stats.rx_frame_errors;
-+              ++priv->stats.rx_errors;
-+      }
++    /** The result of the last H/W DMA generated checksum operation */
++    u16                       tx_csum_result_;
 +
-+      return desc_used;
-+}
++    /** Whether we deal in jumbo frames */
++    int                       jumbo_;
 +
-+/*
-+ * NAPI receive polling method
-+ */
-+static int poll(
-+      struct napi_struct *napi,
-+      int                 budget)
-+{
-+      gmac_priv_t *priv = container_of(napi, gmac_priv_t, napi_struct);
-+      struct net_device *dev = priv->netdev;
-+    int rx_work_limit = budget;
-+    int work_done = 0;
-+    int continue_polling;
-+    int finished;
-+    int available;
-+      int desc_since_refill = 0;
++    volatile int              mii_init_media;
++    volatile int              phy_force_negotiation;
 +
-+    finished = 0;
-+    do {
-+        u32 status;
++#ifdef CONFIG_LEON_COPRO
++    /** DMA coherent memory for CoPro's parameter storage */
++    copro_params_t  *shared_copro_params_;
++    dma_addr_t       shared_copro_params_pa_;
 +
-+        // While there are receive polling jobs to be done
-+        while (rx_work_limit) {
-+                      int desc_used;
++    /** ARM's local CoPro parameter storage */
++    copro_params_t   copro_params_;
 +
-+                      if (unlikely(priv->rx_buffers_per_page)) {
-+                              desc_used = process_rx_packet(priv);
-+                      } else {
-+                              desc_used = process_rx_packet_skb(priv);
-+                      }
++    /** Queue for commands/acks to/from CoPro */
++    int              copro_a_irq_;
++    int              copro_a_irq_alloced_;
++    int              copro_b_irq_;
++    int              copro_b_irq_alloced_;
++    cmd_que_t        cmd_queue_;
++    tx_que_t         tx_queue_;
++    int              copro_cmd_que_num_entries_;
++    int              copro_tx_que_num_entries_;
++      struct semaphore copro_stop_complete_semaphore_;
++      struct list_head copro_tx_skb_list_;
++      int                              copro_tx_skb_list_count_;
++#endif // CONFIG_LEON_COPRO
 +
-+                      if (!desc_used) {
-+                              break;
-+                      }
++    spinlock_t       cmd_que_lock_;
++      u32                               rx_buffer_size_;
++      int                               rx_buffers_per_page;
 +
-+            // Increment count of processed packets
-+            ++work_done;
++      gmac_dma_desc_t *tx_desc_shadow_;
++      gmac_dma_desc_t *rx_desc_shadow_;
 +
-+            // Decrement our remaining budget
-+            if (rx_work_limit > 0) {
-+                --rx_work_limit;
-+            }
++      struct napi_struct napi_struct;
 +
-+            // Rx overflows seem to upset the GMAC, so try to ensure we never see them
-+                      desc_since_refill += desc_used;
-+            if (desc_since_refill >= DESC_SINCE_REFILL_LIMIT) {
-+                desc_since_refill = 0;
-+                refill_rx_ring(dev);
-+            }
-+        }
++      /** sysfs dir tree root for recovery button driver */
++      struct kset        link_state_kset;
++      struct kobject     link_state_kobject;
++      struct work_struct link_state_change_work;
++      int                link_state;
++} gmac_priv_t;
 +
-+        if (rx_work_limit) {
-+            // We have unused budget remaining, but apparently no Rx packets to
-+            // process
-+            available = 0;
++#endif        //  #if !defined(__GMAC_H__)
 +
-+            // Clear any RI status so we don't immediately get reinterrupted
-+            // when we leave polling, due to either a new RI event, or a left
-+            // over interrupt from one of the RX descriptors we've already
-+            // processed
-+            status = dma_reg_read(priv, DMA_STATUS_REG);
-+            if (status & (1UL << DMA_STATUS_RI_BIT)) {
-+                // Ack the RI, including the normal summary sticky bit
-+                dma_reg_write(priv, DMA_STATUS_REG, ((1UL << DMA_STATUS_RI_BIT)  |
-+                                                     (1UL << DMA_STATUS_NIS_BIT)));
+diff -Nurd linux-2.6.24.4/arch/arm/mach-hipox/gmac-napi.c linux-2.6.24/arch/arm/mach-hipox/gmac-napi.c
+--- linux-2.6.24.4/arch/arm/mach-hipox/gmac-napi.c     1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/mach-hipox/gmac-napi.c       2010-01-14 14:01:15.000000000 +0100
+@@ -0,0 +1,3637 @@
++/*
++ * linux/arch/arm/mach-hipox/gmac.c
++ *
++ * Copyright (C) 2005 Oxford Semiconductor Ltd
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
 +
-+                // Must check again for available RX descriptors, in case the RI
-+                // status came from a new RX descriptor
-+                available = rx_available_for_read(&priv->rx_gmac_desc_list_info, 0);
-+            }
++#include <linux/crc32.h>
++#include <linux/version.h>
++#include <linux/init.h>
++#include <linux/errno.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/dma-mapping.h>
++#include <linux/delay.h>
++#include <linux/in.h>
++#include <net/ip.h>
++#include <linux/tcp.h>
++#include <linux/udp.h>
++#include <asm/io.h>
++#include <asm/arch/hardware.h>
++#include <asm/arch/irqs.h>
 +
-+            if (!available) {
-+                // We have budget left but no Rx packets to process so stop
-+                // polling
-+                continue_polling = 0;
-+                finished = 1;
-+            }
-+        } else {
-+            // If we have consumed all our budget, don't cancel the
-+            // poll, the NAPI instructure assumes we won't
-+            continue_polling = 1;
++#ifdef CONFIG_LEON_COPRO
++#include <asm/arch/leon-program.h>
++#endif // CONFIG_LEON_COPRO
 +
-+            // Must leave poll() routine as no budget left
-+            finished = 1;
-+        }
-+    } while (!finished);
++//#define GMAC_DEBUG
++#undef GMAC_DEBUG
 +
-+    // Attempt to fill any empty slots in the RX ring
-+    refill_rx_ring(dev);
++#include "gmac.h"
++#include "gmac_ethtool.h"
++#include "gmac_phy.h"
++#include "gmac_desc.h"
++#include "gmac_reg.h"
 +
-+    // Decrement the budget even if we didn't process any packets
-+    if (!work_done) {
-+        work_done = 1;
-+    }
++//#define DUMP_REGS_ON_GMAC_UP
 +
-+    if (!continue_polling) {
-+        // No more received packets to process so return to interrupt mode
-+        netif_rx_complete(dev, napi);
++#define MAX_GMAC_UNITS 1
 +
-+        // Enable interrupts caused by received packets that may have been
-+              // disabled in the ISR before entering polled mode
-+        gmac_int_en_set(priv, (1UL << DMA_INT_ENABLE_RI_BIT) |
-+                              (1UL << DMA_INT_ENABLE_RU_BIT) |
-+                                                         (1UL << DMA_INT_ENABLE_OV_BIT));
-+    }
++#define ALLOW_AUTONEG
 +
-+    return work_done;
-+}
++//#define ALLOW_OX800_1000M
 +
-+#if defined(CONFIG_LEON_COPRO) && defined(CONFIG_LEON_OFFLOAD_TX)
-+static void copro_fill_tx_job(
-+    volatile gmac_tx_que_ent_t *job,
-+    struct sk_buff             *skb)
-+{
-+    int i;
-+    int nr_frags = skb_shinfo(skb)->nr_frags;
-+    unsigned short flags = 0;
-+    dma_addr_t hdr_dma_address;
++//#define SUPPORT_IPV6
 +
-+    // if too many fragments call sbk_linearize()
-+    // and take the CPU memory copies hit 
-+    if (nr_frags > COPRO_NUM_TX_FRAGS_DIRECT) {
-+        int err;
-+        printk(KERN_WARNING "Fill: linearizing socket buffer as required %d frags and have only %d\n", nr_frags, COPRO_NUM_TX_FRAGS_DIRECT);
-+        err = skb_linearize(skb);
-+        if (err) {
-+            panic("Fill: No free memory");
-+        }
++#ifdef CONFIG_LEON_COPRO
++//#define TEST_COPRO
++#define COPRO_RX_MITIGATION 0   /* No Rx mitigation in CoPro */
++#define COPRO_RX_MITIGATION_FRAMES 5
++#define COPRO_RX_MITIGATION_USECS 500
 +
-+        // update nr_frags
-+        nr_frags = skb_shinfo(skb)->nr_frags;
-+    }
++#define COPRO_TX_QUEUE_NUM_ENTRIES  4
++#define COPRO_CMD_QUEUE_NUM_ENTRIES 6
++#define COPRO_MAX_QUEUED_TX_SKBS    16
++#endif // CONFIG_LEON_COPRO
 +
-+    // Get a DMA mapping of the packet's data
-+    hdr_dma_address = dma_map_single(0, skb->data, skb_headlen(skb), DMA_TO_DEVICE);
-+    BUG_ON(dma_mapping_error(hdr_dma_address));
++#ifdef CONFIG_LEON_OFFLOAD_TX
++#define NUM_RX_DMA_DESCRIPTORS  NUM_GMAC_DMA_DESCRIPTORS
++#define NUM_TX_DMA_DESCRIPTORS  0
++#else
++#define NUM_RX_DMA_DESCRIPTORS (NUM_GMAC_DMA_DESCRIPTORS / 2)
++#define NUM_TX_DMA_DESCRIPTORS (NUM_GMAC_DMA_DESCRIPTORS - NUM_RX_DMA_DESCRIPTORS)
++#endif // CONFIG_LEON_OFFLOAD_TX
 +
-+    // Allocate storage for remainder of fragments and create DMA mappings
-+    // Get a DMA mapping for as many fragments as will fit into the first level
-+    // fragment info. storage within the job structure
-+    for (i=0; i < nr_frags; ++i) {
-+        struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
-+        job->frag_ptr_[i] = dma_map_page(0, frag->page, frag->page_offset, frag->size, DMA_TO_DEVICE);
-+        job->frag_len_[i] = frag->size;
-+    }
++#if (((NUM_RX_DMA_DESCRIPTORS) + (NUM_TX_DMA_DESCRIPTORS)) > (NUM_GMAC_DMA_DESCRIPTORS))
++#error "GMAC TX+RX descriptors exceed allocation"
++#endif
 +
-+    // Is h/w checksumming and possibly TSO required
-+    if (likely((skb->ip_summed == CHECKSUM_PARTIAL) &&
-+               (ntohs(skb->protocol) == ETH_P_IP))) {
-+        flags |= (1UL << TX_JOB_FLAGS_ACCELERATE_BIT);
-+    }
++#define DESC_SINCE_REFILL_LIMIT ((NUM_RX_DMA_DESCRIPTORS) / 4)
 +
-+    // Fill the job description with information about the packet
-+    job->skb_         = (u32)skb;
-+    job->len_         = skb->len;
-+    job->data_len_    = skb->data_len;
-+    job->ethhdr_      = hdr_dma_address;
-+    job->iphdr_       = hdr_dma_address + (skb_network_header(skb) - skb->data);
-+    job->iphdr_csum_  = ((struct iphdr*)skb_network_header(skb))->check;
-+    job->tso_segs_    = skb_shinfo(skb)->gso_segs;
-+    job->tso_size_    = skb_shinfo(skb)->gso_size;
-+    job->flags_       = flags;
-+    job->statistics_  = 0;
-+}
++static const u32 MAC_BASE_OFFSET = 0x0000;
++static const u32 DMA_BASE_OFFSET = 0x1000;
 +
-+static void copro_free_tx_resources(volatile gmac_tx_que_ent_t* job)
-+{
-+    int i;
-+    struct sk_buff* skb = (struct sk_buff*)job->skb_;
-+    int nr_frags = skb_shinfo(skb)->nr_frags;
++static const int MIN_PACKET_SIZE = 68;
++static const int NORMAL_PACKET_SIZE = 1500;
++static const int MAX_JUMBO = 9000;
 +
-+    // This should never happen, since we check space when we filled
-+    // the job in copro_fill_tx_job
-+    if (nr_frags > COPRO_NUM_TX_FRAGS_DIRECT) {
-+        panic("Free: Insufficient fragment storage, required %d, have only %d", nr_frags, COPRO_NUM_TX_FRAGS_DIRECT);
-+    }
++#define RX_BUFFER_SIZE 796    // Must be multiple of 4, If not defined will size buffer to hold a single MTU-sized packet
 +
-+    // Release the DMA mapping for the data directly referenced by the SKB
-+    dma_unmap_single(0, job->ethhdr_, skb_headlen(skb), DMA_TO_DEVICE);
++#ifdef CONFIG_HIPOX_VERSION_0X800
++static const int EXTRA_RX_SKB_SPACE = 24;     // Has extra 2 bytes of Rx payload csum
++#else // CONFIG_HIPOX_VERSION_0X800
++static const int EXTRA_RX_SKB_SPACE = 22;     // Ethernet header 14, VLAN 4, CRC 4
++#endif // CONFIG_HIPOX_VERSION_0X800
 +
-+    // Release the DMA mapping for any fragments in the first level fragment
-+    // info. storage within the job structure
-+    for (i=0; (i < nr_frags) && (i < COPRO_NUM_TX_FRAGS_DIRECT); ++i) {
-+        dma_unmap_page(0, job->frag_ptr_[i], job->frag_len_[i], DMA_TO_DEVICE);
-+    }
++// The amount of header to copy from a receive packet into the skb buffer
++static const int GMAC_HLEN = 66;
 +
-+    // Inform the network stack that we've finished with the packet
-+    dev_kfree_skb_irq(skb);
-+}
++#define GMAC_ALLOC_ORDER 0
++static const int GMAC_ALLOC_SIZE = ((1 << GMAC_ALLOC_ORDER) * PAGE_SIZE);
 +
-+static void copro_process_pending_tx_skbs(
-+    struct net_device          *dev,
-+    volatile gmac_tx_que_ent_t *job)
-+{
-+    gmac_priv_t *priv = (gmac_priv_t*)netdev_priv(dev);
++static const u32 AUTO_NEGOTIATION_WAIT_TIMEOUT_MS = 5000;
 +
-+    // Process pending SKBs, oldest first
-+    do {
-+        // Get the oldest pending SKB
-+        struct sk_buff *skb;
-+        struct list_head *entry = priv->copro_tx_skb_list_.next;
-+        BUG_ON(!entry);
-+        list_del(entry);
++static const u32 NAPI_POLL_WEIGHT = 64;
++static const u32 NAPI_OOM_POLL_INTERVAL_MS = 50;
 +
-+        skb = list_entry(entry, struct sk_buff, cb);
-+        BUG_ON(!skb);
++static const int WATCHDOG_TIMER_INTERVAL = 500*HZ/1000;
 +
-+        // Keep track of how many entries are in the pending SKB list
-+        --priv->copro_tx_skb_list_count_;
++#define AUTO_NEG_MS_WAIT 500
++static const int AUTO_NEG_INTERVAL = (AUTO_NEG_MS_WAIT)*HZ/1000;
++static const int START_RESET_INTERVAL = 50*HZ/1000;
++static const int RESET_INTERVAL = 10*HZ/1000;
 +
-+        // Fill the Tx offload job with the network packet's details
-+        copro_fill_tx_job(job, skb);
++static const int GMAC_RESET_TIMEOUT_MS = 10000;
 +
-+        // Enqueue the new Tx offload job with the CoPro
-+        tx_que_new_job(dev, job);
++static int debug = 0;
 +
-+        if (list_empty(&priv->copro_tx_skb_list_)) {
-+            // No more pending SKBs
-+            break;
-+        }
-+    } while ((job = tx_que_get_idle_job(dev)));
-+}
++MODULE_AUTHOR("Brian Clarke (Oxford Semiconductor Ltd)");
++MODULE_DESCRIPTION("GMAC Network Driver");
++MODULE_LICENSE("GPL");
++MODULE_VERSION("v2.0");
 +
-+static void finish_xmit(struct net_device *dev)
-+{
-+    gmac_priv_t                *priv = (gmac_priv_t*)netdev_priv(dev);
-+    volatile gmac_tx_que_ent_t *job;
++/* Ethernet MAC adr to assign to interface */
++static int mac_adr[] = { 0x00, 0x30, 0xe0, 0x00, 0x00, 0x00 };
++module_param_array(mac_adr, int, NULL, S_IRUGO);
 +
-+    // Process all available completed jobs
-+    while ((job = tx_que_get_finished_job(dev))) {
-+        int aborted;
-+        int carrier;
-+        int collisions;
-+        u32 statistics = job->statistics_;
++/* PHY type kernel cmdline options */
++static int phy_is_rgmii = 0;
++module_param(phy_is_rgmii, int, S_IRUGO);
 +
-+        copro_free_tx_resources(job);
++/* Parse netdev kernel cmdline options */
++static int __init do_setup(char *str)
++{
++    int i;
++    int ints[5];    // Hold arg count and four args
++      u32 mac_hi = 0;
++      u32 mac_lo = 0;
 +
-+        // Accumulate TX statistics returned by CoPro in the job structure
-+        priv->stats.tx_bytes   += (statistics & TX_JOB_STATS_BYTES_MASK)   >> TX_JOB_STATS_BYTES_BIT;
-+        priv->stats.tx_packets += (statistics & TX_JOB_STATS_PACKETS_MASK) >> TX_JOB_STATS_PACKETS_BIT;
-+        aborted    = (statistics & TX_JOB_STATS_ABORT_MASK)     >> TX_JOB_STATS_ABORT_BIT;
-+        carrier    = (statistics & TX_JOB_STATS_CARRIER_MASK)   >> TX_JOB_STATS_CARRIER_BIT;
-+        collisions = (statistics & TX_JOB_STATS_COLLISION_MASK) >> TX_JOB_STATS_COLLISION_BIT;
-+        priv->stats.tx_aborted_errors += aborted;
-+        priv->stats.tx_carrier_errors += carrier;
-+        priv->stats.collisions        += collisions;
-+        priv->stats.tx_errors += (aborted + carrier);
++      /* Get the netdev bootargs parameters */
++    get_options(str, sizeof(ints)/sizeof(int), ints);
++    for (i=1; i<=ints[0]; i++) {
++        switch (i) {
++            case 3:
++                mac_hi = ints[i];
++                break;
++            case 4:
++                mac_lo = ints[i];
++                break;
++        }
 +    }
 +
-+    // Process any queued pending SKBs for which resources are available
-+    if (priv->copro_tx_skb_list_count_ && (job = tx_que_get_idle_job(dev))) {
-+        copro_process_pending_tx_skbs(dev, job);
++      /* Break down the mac adr into its components */
++      for (i=0; i < sizeof(mac_adr)/sizeof(int); i++) {
++              if (i < sizeof(u32)) {
++                      mac_adr[i] = ((mac_hi >> (((sizeof(u32)-1)-i)*8)) & 0xff);
++              } else {
++                      mac_adr[i] = ((mac_lo >> (((sizeof(u32)+1)-i)*8)) & 0xff);
++              }
++      }
 +
-+        // Record start of transmission, so timeouts will work once they're
-+        // implemented
-+        dev->trans_start = jiffies;
++      return 0;
++}
++__setup("netdev=",do_setup);
 +
-+        // Interrupt the CoPro to cause it to examine the Tx offload queue
-+        wmb();
-+        writel(1UL << COPRO_SEM_INT_TX, SYS_CTRL_SEMA_SET_CTRL);
++#ifdef DUMP_REGS_ON_GMAC_UP
++static void dump_mac_regs(u32 macBase, u32 dmaBase)
++{
++    int n = 0;
++
++    for (n=0; n<0x60; n+=4) {
++        printk(KERN_INFO "MAC Register %08x (%08x) = %08x\n", n, macBase+n, readl(macBase+n));
 +    }
 +
-+    // If the network stack's Tx queue was stopped and we now have resources
-+    // to process more Tx offload jobs
-+    if (netif_queue_stopped(dev) &&
-+        !tx_que_is_full(&priv->tx_queue_) &&
-+        !priv->copro_tx_skb_list_count_) {
-+        // Restart the network stack's TX queue
-+        netif_wake_queue(dev);
++    for (n=0; n<0x60; n+=4) {
++        printk(KERN_INFO "DMA Register %08x (%08x) = %08x\n", n, dmaBase+n, readl(dmaBase+n));
 +    }
 +}
-+#else
-+static void finish_xmit(struct net_device *dev)
-+{
-+    gmac_priv_t *priv = (gmac_priv_t*)netdev_priv(dev);
-+    unsigned     descriptors_freed = 0;
-+    u32          desc_status = 0;
-+
-+    // Handle transmit descriptors for the completed packet transmission
-+    while (1) {
-+        struct sk_buff *skb;
-+        tx_frag_info_t  fragment;
-+        int             buffer_owned;
-+              int                              desc_index;
++#endif // DUMP_REGS_ON_GMAC_UP
 +
-+        // Get tx descriptor content, accumulating status for all buffers
-+        // contributing to each packet
-+              desc_index = get_tx_descriptor(priv, &skb, &desc_status, &fragment, &buffer_owned);
++#ifdef CONFIG_LEON_COPRO
++static struct semaphore copro_update_semaphore;
 +
-+              if (desc_index < 0) {
-+                      // No more completed Tx packets
-+                      break;
-+              }
++static void copro_update_callback(volatile gmac_cmd_que_ent_t* entry)
++{
++    up(&copro_update_semaphore);
++}
 +
-+        // Only unmap DMA buffer if descriptor owned the buffer
-+        if (buffer_owned) {
-+            // Release the DMA mapping for the buffer
-+            dma_unmap_single(0, fragment.phys_adr, fragment.length, DMA_TO_DEVICE);
-+        }
++static struct semaphore copro_start_semaphore;
 +
-+        // When all buffers contributing to a packet have been processed
-+        if (skb) {
-+            // Check the status of the transmission
-+            if (likely(is_tx_valid(desc_status))) {
-+                priv->stats.tx_bytes += skb->len;
-+                priv->stats.tx_packets++;
-+            } else {
-+                priv->stats.tx_errors++;
-+                if (is_tx_aborted(desc_status)) {
-+                    ++priv->stats.tx_aborted_errors;
-+                }
-+                if (is_tx_carrier_error(desc_status)) {
-+                    ++priv->stats.tx_carrier_errors;
-+                }
-+            }
++static void copro_start_callback(volatile gmac_cmd_que_ent_t* entry)
++{
++    up(&copro_start_semaphore);
++}
 +
-+            if (unlikely(is_tx_collision_error(desc_status))) {
-+                ++priv->stats.collisions;
-+            }
++static struct semaphore copro_rx_enable_semaphore;
 +
-+            // Inform the network stack that packet transmission has finished
-+            dev_kfree_skb_irq(skb);
++static void copro_rx_enable_callback(volatile gmac_cmd_que_ent_t* entry)
++{
++    up(&copro_rx_enable_semaphore);
++}
++#endif // CONFIG_LEON_COPRO
 +
-+            // Start accumulating status for the next packet
-+            desc_status = 0;
-+        }
++static void gmac_int_en_set(
++    gmac_priv_t *priv,
++    u32          mask)
++{
++    unsigned long irq_flags = 0;
 +
-+        // Track how many descriptors we make available, so we know
-+        // if we need to re-start of network stack's TX queue processing
-+        ++descriptors_freed;
-+    }
++#ifdef CONFIG_LEON_COPRO
++    int cmd_queue_result = -1;
++    while (cmd_queue_result) {
++        if (in_irq())
++            spin_lock(&priv->cmd_que_lock_);
++        else
++            spin_lock_irqsave(&priv->cmd_que_lock_, irq_flags);
 +
-+    // If the TX queue is stopped, there may be a pending TX packet waiting to
-+    // be transmitted
-+    if (unlikely(netif_queue_stopped(dev))) {
-+              // No locking with hard_start_xmit() required, as queue is already
-+              // stopped so hard_start_xmit() won't touch the h/w
++        cmd_queue_result = cmd_que_queue_cmd(&priv->cmd_queue_, GMAC_CMD_INT_EN_SET, mask, 0);
 +
-+        // If any TX descriptors have been freed and there is an outstanding TX
-+        // packet waiting to be queued due to there not having been a TX
-+        // descriptor available when hard_start_xmit() was presented with an skb
-+        // by the network stack
-+        if (priv->tx_pending_skb) {
-+            // Construct the GMAC specific DMA descriptor
-+            if (set_tx_descriptor(priv,
-+                                  priv->tx_pending_skb,
-+                                  priv->tx_pending_fragments,
-+                                  priv->tx_pending_fragment_count,
-+                                  priv->tx_pending_skb->ip_summed == CHECKSUM_PARTIAL) >= 0) {
-+                // No TX packets now outstanding
-+                priv->tx_pending_skb = 0;
-+                priv->tx_pending_fragment_count = 0;
++        if (in_irq())
++            spin_unlock(&priv->cmd_que_lock_);
++        else
++            spin_unlock_irqrestore(&priv->cmd_que_lock_, irq_flags);
++    }
 +
-+                // We have used one of the TX descriptors freed by transmission
-+                // completion processing having occured above
-+                --descriptors_freed;
++    // Interrupt the CoPro so it sees the new command
++    writel(1UL << COPRO_SEM_INT_CMD, SYS_CTRL_SEMA_SET_CTRL);
++#else
++    if (in_irq())
++        spin_lock(&priv->cmd_que_lock_);
++    else
++        spin_lock_irqsave(&priv->cmd_que_lock_, irq_flags);
 +
-+                // Issue a TX poll demand to restart TX descriptor processing, as we
-+                // have just added one, in case it had found there were no more
-+                // pending transmission
-+                dma_reg_write(priv, DMA_TX_POLL_REG, 0);
-+            }
-+        }
++    dma_reg_set_mask(priv, DMA_INT_ENABLE_REG, mask);
 +
-+        // If there are TX descriptors available we should restart the TX queue
-+        if (descriptors_freed) {
-+            // The TX queue had been stopped by hard_start_xmit() due to lack of
-+            // TX descriptors, so restart it now that we've freed at least one
-+            netif_wake_queue(dev);
-+        }
-+    }
++    if (in_irq())
++        spin_unlock(&priv->cmd_que_lock_);
++    else
++        spin_unlock_irqrestore(&priv->cmd_que_lock_, irq_flags);
++#endif // CONFIG_LEON_COPRO
 +}
-+#endif // CONFIG_LEON_COPRO && CONFIG_LEON_OFFLOAD_TX
 +
-+#ifndef CONFIG_LEON_COPRO
-+static void process_non_dma_ints(u32 raw_status)
++#ifdef CONFIG_LEON_COPRO
++static struct semaphore copro_int_clr_semaphore;
++static unsigned long    copro_int_clr_return;
++
++static void copro_int_clr_callback(volatile gmac_cmd_que_ent_t* entry)
 +{
-+    printk(KERN_ERR "Found GPI/GMI/GLI interrupt\n");
++    copro_int_clr_return = entry->operand_;
++    up(&copro_int_clr_semaphore);
 +}
-+#endif // !CONFIG_LEON_COPRO
++#endif // CONFIG_LEON_COPRO
 +
-+#ifdef CONFIG_LEON_COPRO
-+static void copro_fwd_intrs_handler(
-+    void *dev_id,
-+    u32   status)
++static void gmac_int_en_clr(
++    gmac_priv_t *priv,
++    u32          mask,
++    u32         *new_value,
++      int          in_atomic)
 +{
-+    struct net_device *dev = (struct net_device *)dev_id;
-+    gmac_priv_t       *priv = (gmac_priv_t*)netdev_priv(dev);
-+    int                restart_watchdog = 0;
-+    int                restart_tx = 0;
-+    int                poll_tx = 0;
-+
-+    // Test for normal receive interrupt
-+    if (status & (1UL << DMA_STATUS_RI_BIT)) {
-+        if (netif_rx_schedule_prep(dev, &priv->napi_struct)) {
-+            // Tell system we have work to be done
-+            __netif_rx_schedule(dev, &priv->napi_struct);
-+        } else {
-+            printk(KERN_ERR "copro_fwd_intrs_handler() %s: RX interrupt while in poll\n", dev->name);
-+        }
-+    }
++#ifdef CONFIG_LEON_COPRO
++    unsigned long irq_flags = 0;
 +
-+    // Test for unavailable RX buffers - CoPro should have disabled
-+    if (unlikely(status & (1UL << DMA_STATUS_RU_BIT))) {
-+        DBG(30, KERN_INFO "int_handler() %s: RX buffer unavailable\n", dev->name);
-+        // Accumulate receive statistics
-+        ++priv->stats.rx_over_errors;
-+        ++priv->stats.rx_errors;
-+    }
++    int cmd_queue_result = -1;
++    while (cmd_queue_result) {
++        if (in_irq())
++            spin_lock(&priv->cmd_que_lock_);
++        else
++            spin_lock_irqsave(&priv->cmd_que_lock_, irq_flags);
 +
-+    // Test for Rx overflow - CoPro should have disabled
-+      if (unlikely(status & (1UL << DMA_STATUS_OVF_BIT))) {
-+              DBG(30, KERN_INFO "int_handler() %s: Rx overflow\n", dev->name);
-+              // Accumulate receive statistics
-+              ++priv->stats.rx_fifo_errors;
-+              ++priv->stats.rx_errors;
-+      }
++        cmd_queue_result = cmd_que_queue_cmd(&priv->cmd_queue_, GMAC_CMD_INT_EN_CLR, mask, copro_int_clr_callback);
 +
-+    // Test for normal TX interrupt
-+    if (status & ((1UL << DMA_STATUS_TI_BIT) |
-+                  (1UL << DMA_STATUS_ETI_BIT))) {
-+#ifndef CONFIG_LEON_OFFLOAD_TX
-+        // Finish packet transmision started by start_xmit
-+        finish_xmit(dev);
-+#endif // !CONFIG_LEON_OFFLOAD_TX
++        if (in_irq())
++            spin_unlock(&priv->cmd_que_lock_);
++        else
++            spin_unlock_irqrestore(&priv->cmd_que_lock_, irq_flags);
 +    }
 +
-+    // Test for abnormal transmitter interrupt where there may be completed
-+    // packets waiting to be processed
-+    if (unlikely(status & ((1UL << DMA_STATUS_TJT_BIT) |
-+                           (1UL << DMA_STATUS_UNF_BIT)))) {
-+#ifndef CONFIG_LEON_OFFLOAD_TX
-+        // Complete processing of any TX packets closed by the DMA
-+        finish_xmit(dev);
-+#endif // !CONFIG_LEON_OFFLOAD_TX
++    // Interrupt the CoPro so it sees the new command
++    writel(1UL << COPRO_SEM_INT_CMD, SYS_CTRL_SEMA_SET_CTRL);
 +
-+        if (status & (1UL << DMA_STATUS_TJT_BIT)) {
-+            // A transmit jabber timeout causes the transmitter to enter the
-+            // stopped state
-+            DBG(50, KERN_INFO "int_handler() %s: TX jabber timeout\n", dev->name);
-+            restart_tx = 1;
++    if (new_value) {
++        // Wait until the CoPro acknowledges that it has stopped
++        if (in_atomic) {
++            while (down_trylock(&copro_int_clr_semaphore)) {
++                udelay(100);
++            }
 +        } else {
-+            DBG(51, KERN_INFO "int_handler() %s: TX underflow\n", dev->name);
++            down_interruptible(&copro_int_clr_semaphore);
 +        }
-+
-+        // Issue a TX poll demand in an attempt to restart TX descriptor
-+        // processing
-+        poll_tx = 1;
++        *new_value = copro_int_clr_return;
 +    }
++#else
++    unsigned long temp;
++    unsigned long irq_flags = 0;
 +
-+    // Test for any of the error states which we deal with directly within
-+    // this interrupt service routine.
-+    if (unlikely(status & ((1UL << DMA_STATUS_ERI_BIT) |
-+                           (1UL << DMA_STATUS_RWT_BIT) |
-+                           (1UL << DMA_STATUS_RPS_BIT) |
-+                           (1UL << DMA_STATUS_TPS_BIT) |
-+                           (1UL << DMA_STATUS_FBE_BIT)))) {
-+        // Test for early RX interrupt
-+        if (status & (1UL << DMA_STATUS_ERI_BIT)) {
-+            // Don't expect to see this, as never enable it
-+            DBG(30, KERN_WARNING "int_handler() %s: Early RX \n", dev->name);
-+        }
++    if (in_irq())
++        spin_lock(&priv->cmd_que_lock_);
++    else
++        spin_lock_irqsave(&priv->cmd_que_lock_, irq_flags);
 +
-+        if (status & (1UL << DMA_STATUS_RWT_BIT)) {
-+            DBG(30, KERN_INFO "int_handler() %s: RX watchdog timeout\n", dev->name);
-+            // Accumulate receive statistics
-+            ++priv->stats.rx_frame_errors;
-+            ++priv->stats.rx_errors;
-+            restart_watchdog = 1;
-+        }
++    temp = dma_reg_clear_mask(priv, DMA_INT_ENABLE_REG, mask);
 +
-+        if (status & (1UL << DMA_STATUS_RPS_BIT)) {
-+            // Mask to extract the receive status field from the status register
-+//            u32 rs_mask = ((1UL << DMA_STATUS_RS_NUM_BITS) - 1) << DMA_STATUS_RS_BIT;
-+//            u32 rs = (status & rs_mask) >> DMA_STATUS_RS_BIT;
-+//            printk("int_handler() %s: RX process stopped 0x%x\n", dev->name, rs);
-+            ++priv->stats.rx_errors;
-+            restart_watchdog = 1;
++    if (in_irq())
++        spin_unlock(&priv->cmd_que_lock_);
++    else
++        spin_unlock_irqrestore(&priv->cmd_que_lock_, irq_flags);
 +
-+            // Restart the receiver
-+            DBG(35, KERN_INFO "int_handler() %s: Restarting receiver\n", dev->name);
-+            change_rx_enable(priv, 1, 0, 1);
-+        }
++    if (new_value) {
++        *new_value = temp;
++    }
++#endif
++}
 +
-+        if (status & (1UL << DMA_STATUS_TPS_BIT)) {
-+            // Mask to extract the transmit status field from the status register
-+//            u32 ts_mask = ((1UL << DMA_STATUS_TS_NUM_BITS) - 1) << DMA_STATUS_TS_BIT;
-+//            u32 ts = (status & ts_mask) >> DMA_STATUS_TS_BIT;
-+//            printk("int_handler() %s: TX process stopped 0x%x\n", dev->name, ts);
-+            ++priv->stats.tx_errors;
-+            restart_watchdog = 1;
-+            restart_tx = 1;
-+        }
++/**
++ * May be invoked from either ISR or process context, so locking must be
++ * invoked appropriate to the return from in_irq()
++ */
++static void change_rx_enable(
++    gmac_priv_t *priv,
++    u32          start,
++    int          waitForAck,
++      int          in_atomic)
++{
++#ifdef CONFIG_LEON_COPRO
++    unsigned long irq_flags = 0;
++    int cmd_queue_result = -1;
 +
-+        // Test for pure error interrupts
-+        if (status & (1UL << DMA_STATUS_FBE_BIT)) {
-+            // Mask to extract the bus error status field from the status register
-+//            u32 eb_mask = ((1UL << DMA_STATUS_EB_NUM_BITS) - 1) << DMA_STATUS_EB_BIT;
-+//            u32 eb = (status & eb_mask) >> DMA_STATUS_EB_BIT;
-+//            printk("int_handler() %s: Bus error 0x%x\n", dev->name, eb);
-+            restart_watchdog = 1;
-+        }
++    while (cmd_queue_result) {
++        if (in_irq())
++            spin_lock(&priv->cmd_que_lock_);
++        else
++            spin_lock_irqsave(&priv->cmd_que_lock_, irq_flags);
 +
-+        if (restart_watchdog) {
-+            // Restart the link/PHY state watchdog immediately, which will
-+            // attempt to restart the system
-+            mod_timer(&priv->watchdog_timer, jiffies);
-+            restart_watchdog = 0;
-+        }
-+    }
++        // Request the CoPro to start/stop GMAC receiver
++        cmd_queue_result =
++            cmd_que_queue_cmd(&priv->cmd_queue_,
++                              GMAC_CMD_CHANGE_RX_ENABLE,
++                              start,
++                              waitForAck ? copro_rx_enable_callback : 0);
 +
-+    if (unlikely(restart_tx)) {
-+        // Restart the transmitter, causes am implicit Tx descriptor list poll
-+        DBG(35, KERN_INFO "int_handler() %s: Restarting transmitter\n", dev->name);
-+#ifndef CONFIG_LEON_OFFLOAD_TX
-+        dma_reg_set_mask(priv, DMA_OP_MODE_REG, (1UL << DMA_OP_MODE_ST_BIT));
-+#endif // !CONFIG_LEON_OFFLOAD_TX
-+        poll_tx = 0;
++        if (in_irq())
++            spin_unlock(&priv->cmd_que_lock_);
++        else
++            spin_unlock_irqrestore(&priv->cmd_que_lock_, irq_flags);
 +    }
 +
-+    if (unlikely(poll_tx)) {
-+        // Issue a TX poll demand in an attempt to restart TX descriptor
-+        // processing
-+        DBG(33, KERN_INFO "int_handler() %s: Issuing Tx poll demand\n", dev->name);
-+#ifndef CONFIG_LEON_OFFLOAD_TX
-+        dma_reg_write(priv, DMA_TX_POLL_REG, 0);
-+#endif // !CONFIG_LEON_OFFLOAD_TX
++    // Interrupt the CoPro so it sees the new command
++    writel(1UL << COPRO_SEM_INT_CMD, SYS_CTRL_SEMA_SET_CTRL);
++
++    if (waitForAck) {
++        // Wait until the CoPro acknowledges that the receiver has been stopped
++        if (in_atomic) {
++            while (down_trylock(&copro_rx_enable_semaphore)) {
++                udelay(100);
++            }
++        } else {
++            down_interruptible(&copro_rx_enable_semaphore);
++        }
 +    }
++#else // CONFIG_LEON_COPRO
++    start ? dma_reg_set_mask(priv, DMA_OP_MODE_REG, 1UL << DMA_OP_MODE_SR_BIT) :
++            dma_reg_clear_mask(priv, DMA_OP_MODE_REG, 1UL << DMA_OP_MODE_SR_BIT);
++#endif // CONFIG_LEON_COPRO
 +}
-+#else // CONFIG_LEON_COPRO 
-+static irqreturn_t int_handler(int int_num, void* dev_id)
-+{
-+    struct net_device *dev = (struct net_device *)dev_id;
-+    gmac_priv_t* priv = (gmac_priv_t*)netdev_priv(dev);
-+    u32 int_enable;
-+    int rx_polling;
-+    u32 raw_status;
-+    u32 status;
 +
-+    /** Read the interrupt enable register to determine if we're in rx poll mode
-+     *  Id like to get rid of this read, if a more efficient way of determining
-+     *  whether we are polling is available */
-+    spin_lock(&priv->cmd_que_lock_);
-+    int_enable = dma_reg_read(priv, DMA_INT_ENABLE_REG);
-+    spin_unlock(&priv->cmd_que_lock_);
-+
-+    rx_polling = !(int_enable & (1UL << DMA_INT_ENABLE_RI_BIT));
++/**
++ * Invoked from the watchdog timer action routine which runs as softirq, so
++ * must disable interrupts when obtaining locks
++ */
++static void change_gig_mode(gmac_priv_t *priv)
++{
++      unsigned int is_gig = priv->mii.using_1000;
 +
-+    // Get interrupt status
-+    raw_status = dma_reg_read(priv, DMA_STATUS_REG);
++#ifdef CONFIG_LEON_COPRO
++    unsigned long irq_flags = 0;
++    int cmd_queue_result = -1;
 +
-+    // MMC, PMT and GLI interrupts are not masked by the interrupt enable
-+    // register, so must deal with them on the raw status
-+    if (unlikely(raw_status & ((1UL << DMA_STATUS_GPI_BIT) |
-+                      (1UL << DMA_STATUS_GMI_BIT) |
-+                      (1UL << DMA_STATUS_GLI_BIT)))) {
-+        process_non_dma_ints(raw_status);
++    while (cmd_queue_result) {
++        spin_lock_irqsave(&priv->cmd_que_lock_, irq_flags);
++        // Request the CoPro to change gigabit mode
++        cmd_queue_result = cmd_que_queue_cmd(&priv->cmd_queue_, GMAC_CMD_CHANGE_GIG_MODE, is_gig, 0);
++        spin_unlock_irqrestore(&priv->cmd_que_lock_, irq_flags);
 +    }
 +
-+    // Get status of enabled interrupt sources
-+    status = raw_status & int_enable;
++    // Interrupt the CoPro so it sees the new command
++    writel(1UL << COPRO_SEM_INT_CMD, SYS_CTRL_SEMA_SET_CTRL);
++#else // CONFIG_LEON_COPRO
++      static const int MAX_TRIES = 1000;
++      int tries = 0;
 +
-+    while (status) {
-+        // Whether the link/PHY watchdog timer should be restarted
-+        int restart_watchdog = 0;
-+        int restart_tx       = 0;
-+        int poll_tx          = 0;
-+        u32 int_disable_mask = 0;
++    // Mask to extract the transmit status field from the status register
++    u32 ts_mask = ((1UL << DMA_STATUS_TS_NUM_BITS) - 1) << DMA_STATUS_TS_BIT;
 +
-+        // Test for RX interrupt resulting from sucessful reception of a packet-
-+        // must do this before ack'ing, else otherwise can get into trouble with
-+        // the sticky summary bits when we try to disable further RI interrupts
-+        if (status & (1UL << DMA_STATUS_RI_BIT)) {
-+//printk("RI ");
-+            // Disable interrupts caused by received packets as henceforth
-+            // we shall poll for packet reception
-+            int_disable_mask |= (1UL << DMA_INT_ENABLE_RI_BIT);
++    // Must stop transmission in order to change store&forward mode
++    dma_reg_clear_mask(priv, DMA_OP_MODE_REG, (1UL << DMA_OP_MODE_ST_BIT));
 +
-+            // Do NAPI compatible receive processing for RI interrupts
-+            if (likely(netif_rx_schedule_prep(dev, &priv->napi_struct))) {
-+                // Remember that we are polling, so we ignore RX events for the
-+                // remainder of the ISR
-+                rx_polling = 1;
++    // Transmission only stops after current Tx frame has completed trans-
++    // mission, so wait for the Tx state machine to enter the stopped state
++    while ((dma_reg_read(priv, DMA_STATUS_REG) & ts_mask) != (DMA_STATUS_TS_STOPPED << DMA_STATUS_TS_BIT)) {
++              mdelay(1);
++              if (unlikely(++tries == MAX_TRIES)) {
++                      break;
++              }
++      }
 +
-+                // Tell system we have work to be done
-+                __netif_rx_schedule(dev, &priv->napi_struct);
-+            } else {
-+                printk(KERN_ERR "int_handler() %s: RX interrupt while in poll\n", dev->name);
-+            }
-+        }
++      if (unlikely(tries == MAX_TRIES)) {
++              printk(KERN_WARNING "Timed out of wait for Tx to stop\n");
++      }
 +
-+        // Test for unavailable RX buffers - must do this before ack'ing, else
-+        // otherwise can get into trouble with the sticky summary bits
-+        if (unlikely(status & (1UL << DMA_STATUS_RU_BIT))) {
-+            printk(/*DBG(30, KERN_INFO */"int_handler() %s: RX buffer unavailable\n", dev->name);
-+            // Accumulate receive statistics
-+            ++priv->stats.rx_over_errors;
-+            ++priv->stats.rx_errors;
++    if (is_gig) {
++        mac_reg_clear_mask(priv, MAC_CONFIG_REG, (1UL << MAC_CONFIG_PS_BIT));
++#ifdef CONFIG_HIPOX_VERSION_0X800
++        // In gigabit mode the OX800 cannot support the required data rate to
++        // the GMAC, so must use store&forward and OX800 doesn't support Tx
++              // checksumming in the GMAC
++        dma_reg_set_mask(priv, DMA_OP_MODE_REG, (1UL << DMA_OP_MODE_SF_BIT));
++#endif // CONFIG_HIPOX_VERSION_0X800
++    } else {
++        mac_reg_set_mask(priv, MAC_CONFIG_REG, (1UL << MAC_CONFIG_PS_BIT));
++#ifdef CONFIG_HIPOX_VERSION_0X800
++        dma_reg_clear_mask(priv, DMA_OP_MODE_REG, (1UL << DMA_OP_MODE_SF_BIT));
++#endif // CONFIG_HIPOX_VERSION_0X800
++    }
 +
-+            // Disable RX buffer unavailable reporting, so we don't get swamped
-+            int_disable_mask |= (1UL << DMA_INT_ENABLE_RU_BIT);
-+        }
++    // Re-start transmission after store&forward change applied
++    dma_reg_set_mask(priv, DMA_OP_MODE_REG, (1UL << DMA_OP_MODE_ST_BIT));
++#endif // CONFIG_LEON_COPRO
++}
 +
-+              if (unlikely(status & (1UL << DMA_STATUS_OVF_BIT))) {
-+                      printk(/*DBG(30, KERN_INFO */"int_handler() %s: RX overflow\n", dev->name);
-+                      // Accumulate receive statistics
-+                      ++priv->stats.rx_fifo_errors;
-+                      ++priv->stats.rx_errors;
++/**
++ * Invoked from the watchdog timer action routine which runs as softirq, so
++ * must disable interrupts when obtaining locks
++ */
++static void change_pause_mode(gmac_priv_t *priv)
++{
++#ifdef CONFIG_LEON_COPRO
++      unsigned int enable_pause = priv->mii.using_pause;
++    unsigned long irq_flags = 0;
++    int cmd_queue_result = -1;
 +
-+            // Disable RX overflow reporting, so we don't get swamped
-+            int_disable_mask |= (1UL << DMA_INT_ENABLE_OV_BIT);
-+              }
++    while (cmd_queue_result) {
++        spin_lock_irqsave(&priv->cmd_que_lock_, irq_flags);
++        // Request the CoPro to change pause mode
++        cmd_queue_result = cmd_que_queue_cmd(&priv->cmd_queue_, GMAC_CMD_CHANGE_PAUSE_MODE, enable_pause, 0);
++        spin_unlock_irqrestore(&priv->cmd_que_lock_, irq_flags);
++    }
 +
-+        // Do any interrupt disabling with a single register write
-+        if (int_disable_mask) {
-+            gmac_int_en_clr(priv, int_disable_mask, 0);
++    // Interrupt the CoPro so it sees the new command
++    writel(1UL << COPRO_SEM_INT_CMD, SYS_CTRL_SEMA_SET_CTRL);
++#else // CONFIG_LEON_COPRO
++#ifndef CONFIG_HIPOX_VERSION_0X800
++      unsigned int enable_pause = priv->mii.using_pause;
 +
-+            // Update our record of the current interrupt enable status
-+            int_enable &= ~int_disable_mask;
-+        }
++    if (enable_pause) {
++        mac_reg_set_mask(priv, MAC_FLOW_CNTL_REG, (1UL << MAC_FLOW_CNTL_TFE_BIT));
++    } else {
++        mac_reg_clear_mask(priv, MAC_FLOW_CNTL_REG, (1UL << MAC_FLOW_CNTL_TFE_BIT));
++    }
++#endif // !CONFIG_HIPOX_VERSION_0X800
++#endif // CONFIG_LEON_COPRO
++}
 +
-+        // The broken GMAC interrupt mechanism with its sticky summary bits
-+        // means that we have to ack all asserted interrupts here; we can't not
-+        // ack the RI interrupt source as we might like to (in order that the
-+        // poll() routine could examine the status) because if it was asserted
-+        // prior to being masked above, then the summary bit(s) would remain
-+        // asserted and cause an immediate re-interrupt.
-+        dma_reg_write(priv, DMA_STATUS_REG, status | ((1UL << DMA_STATUS_NIS_BIT) |
-+                                                      (1UL << DMA_STATUS_AIS_BIT)));
++static void refill_rx_ring(struct net_device *dev)
++{
++    gmac_priv_t *priv = (gmac_priv_t*)netdev_priv(dev);
++      int filled = 0;
 +
-+        // Test for normal TX interrupt
-+        if (status & ((1UL << DMA_STATUS_TI_BIT) |
-+                      (1UL << DMA_STATUS_ETI_BIT))) {
-+            // Finish packet transmision started by start_xmit
-+            finish_xmit(dev);
-+        }
++      if (unlikely(priv->rx_buffers_per_page)) {
++              // Receive into pages
++              struct page *page = 0;
++              int offset = 0;
++              dma_addr_t phys_adr = 0;
 +
-+        // Test for abnormal transmitter interrupt where there may be completed
-+        // packets waiting to be processed
-+        if (unlikely(status & ((1UL << DMA_STATUS_TJT_BIT) |
-+                               (1UL << DMA_STATUS_UNF_BIT)))) {
-+            // Complete processing of any TX packets closed by the DMA
-+            finish_xmit(dev);
++              // While there are empty RX descriptor ring slots
++              while (1) {
++                      int available;
++                      int desc;
++                      rx_frag_info_t frag_info;
 +
-+            if (status & (1UL << DMA_STATUS_TJT_BIT)) {
-+                // A transmit jabber timeout causes the transmitter to enter the
-+                // stopped state
-+                DBG(50, KERN_INFO "int_handler() %s: TX jabber timeout\n", dev->name);
-+                restart_tx = 1;
-+            } else {
-+                DBG(51, KERN_INFO "int_handler() %s: TX underflow\n", dev->name);
-+            }
++                      // Have we run out of space in the current page?
++                      if (offset + NET_IP_ALIGN + priv->rx_buffer_size_ > GMAC_ALLOC_SIZE) {
++                              page = 0;
++                              offset = 0;
++                      }
 +
-+            // Issue a TX poll demand in an attempt to restart TX descriptor
-+            // processing
-+            poll_tx = 1;
-+        }
++                      if (!page) {
++                              // Start a new page
++                              available = available_for_write(&priv->rx_gmac_desc_list_info);
++                              if (available < priv->rx_buffers_per_page) {
++                                      break;
++                              }
 +
-+        // Test for any of the error states which we deal with directly within
-+        // this interrupt service routine.
-+        if (unlikely(status & ((1UL << DMA_STATUS_ERI_BIT) |
-+                               (1UL << DMA_STATUS_RWT_BIT) |
-+                               (1UL << DMA_STATUS_RPS_BIT) |
-+                               (1UL << DMA_STATUS_TPS_BIT) |
-+                               (1UL << DMA_STATUS_FBE_BIT)))) {
-+            // Test for early RX interrupt
-+            if (status & (1UL << DMA_STATUS_ERI_BIT)) {
-+                // Don't expect to see this, as never enable it
-+                DBG(30, KERN_WARNING "int_handler() %s: Early RX \n", dev->name);
-+            }
++                              // Allocate a page to hold a received packet
++                              page = alloc_pages(GFP_ATOMIC, GMAC_ALLOC_ORDER);
++                              if (unlikely(page == NULL)) {
++                                      printk(KERN_WARNING "refill_rx_ring() Could not alloc page\n");
++                                      break;
++                              }
 +
-+            if (status & (1UL << DMA_STATUS_RWT_BIT)) {
-+                DBG(30, KERN_INFO "int_handler() %s: RX watchdog timeout\n", dev->name);
-+                // Accumulate receive statistics
-+                ++priv->stats.rx_frame_errors;
-+                ++priv->stats.rx_errors;
-+                restart_watchdog = 1;
-+            }
++                              // Get a consistent DMA mapping for the entire page that will be
++                              // DMAed to - causing an invalidation of any entries in the CPU's
++                              // cache covering the memory region
++                              phys_adr = dma_map_page(0, page, 0, GMAC_ALLOC_SIZE, DMA_FROM_DEVICE);
++                              BUG_ON(dma_mapping_error(phys_adr));
++                      } else {
++                              // Using the current page again
++                              get_page(page);
++                      }
 +
-+            if (status & (1UL << DMA_STATUS_RPS_BIT)) {
-+                              // Mask to extract the receive status field from the status register
-+                              u32 rs_mask = ((1UL << DMA_STATUS_RS_NUM_BITS) - 1) << DMA_STATUS_RS_BIT;
-+                              u32 rs = (status & rs_mask) >> DMA_STATUS_RS_BIT;
-+                              printk(/*DBG(30, KERN_INFO */"int_handler() %s: RX process stopped 0x%x\n", dev->name, rs);
-+                              ++priv->stats.rx_errors;
-+                              restart_watchdog = 1;
++                      // Ensure IP header is quad aligned
++                      offset += NET_IP_ALIGN;
++                      frag_info.page = page;
++                      frag_info.length = priv->rx_buffer_size_;
++                      frag_info.phys_adr = phys_adr + offset;
 +
-+                // Restart the receiver
-+                printk(/*DBG(35, KERN_INFO */"int_handler() %s: Restarting receiver\n", dev->name);
-+                dma_reg_set_mask(priv, DMA_OP_MODE_REG, (1UL << DMA_OP_MODE_SR_BIT));
-+            }
++                      // Try to associate a descriptor with the fragment info
++                      desc = set_rx_descriptor(priv, &frag_info);
++                      if (desc >= 0) {
++                              filled = 1;
++                      } else {
++                              // Failed to associate the descriptor, so release the DMA mapping
++                              // for the socket buffer
++                              dma_unmap_page(0, frag_info.phys_adr, frag_info.length, DMA_FROM_DEVICE);
 +
-+            if (status & (1UL << DMA_STATUS_TPS_BIT)) {
-+                              // Mask to extract the transmit status field from the status register
-+//                            u32 ts_mask = ((1UL << DMA_STATUS_TS_NUM_BITS) - 1) << DMA_STATUS_TS_BIT;
-+//                            u32 ts = (status & ts_mask) >> DMA_STATUS_TS_BIT;
-+//                            DBG(30, KERN_INFO "int_handler() %s: TX process stopped 0x%x\n", dev->name, ts);
-+                ++priv->stats.tx_errors;
-+                restart_watchdog = 1;
-+                restart_tx = 1;
-+            }
++                              // No more RX descriptor ring entries to refill
++                              break;
++                      }
 +
-+            // Test for pure error interrupts
-+            if (status & (1UL << DMA_STATUS_FBE_BIT)) {
-+                              // Mask to extract the bus error status field from the status register
-+//                            u32 eb_mask = ((1UL << DMA_STATUS_EB_NUM_BITS) - 1) << DMA_STATUS_EB_BIT;
-+//                            u32 eb = (status & eb_mask) >> DMA_STATUS_EB_BIT;
-+//                            DBG(30, KERN_INFO "int_handler() %s: Bus error 0x%x\n", dev->name, eb);
-+                restart_watchdog = 1;
-+            }
++                      // Account for the space used in the current page
++                      offset += frag_info.length;
 +
-+            if (restart_watchdog) {
-+                // Restart the link/PHY state watchdog immediately, which will
-+                // attempt to restart the system
-+                mod_timer(&priv->watchdog_timer, jiffies);
-+                restart_watchdog = 0;
-+            }
-+        }
++                      // Start next packet on a cacheline boundary
++                      offset = SKB_DATA_ALIGN(offset);
++              }
++      } else {
++              // Preallocate MTU-sized SKBs
++              while (1) {
++                      struct sk_buff *skb;
++                      rx_frag_info_t frag_info;
++                      int desc;
 +
-+        if (unlikely(restart_tx)) {
-+            // Restart the transmitter
-+            DBG(35, KERN_INFO "int_handler() %s: Restarting transmitter\n", dev->name);
-+            dma_reg_set_mask(priv, DMA_OP_MODE_REG, (1UL << DMA_OP_MODE_ST_BIT));
-+        }
++                      if (!available_for_write(&priv->rx_gmac_desc_list_info)) {
++                              break;
++                      }
 +
-+        if (unlikely(poll_tx)) {
-+            // Issue a TX poll demand in an attempt to restart TX descriptor
-+            // processing
-+            DBG(33, KERN_INFO "int_handler() %s: Issuing Tx poll demand\n", dev->name);
-+            dma_reg_write(priv, DMA_TX_POLL_REG, 0);
-+        }
++                      // Allocate a new skb for the descriptor ring which is large enough
++                      // for any packet received from the link
++                      skb = dev_alloc_skb(priv->rx_buffer_size_ + NET_IP_ALIGN);
++                      if (!skb) {
++                              // Can't refill any more RX descriptor ring entries
++                              break;
++                      } else {
++                              // Despite what the comments in the original code from Synopsys
++                              // claimed, the GMAC DMA can cope with non-quad aligned buffers
++                              // - it will always perform quad transfers but zero/ignore the
++                              // unwanted bytes.
++                              skb_reserve(skb, NET_IP_ALIGN);
++                      }
 +
-+        // Read the record of current interrupt requests again, in case some
-+        // more arrived while we were processing
-+        raw_status = dma_reg_read(priv, DMA_STATUS_REG);
++                      // Get a consistent DMA mapping for the memory to be DMAed to
++                      // causing invalidation of any entries in the CPU's cache covering
++                      // the memory region
++                      frag_info.page = (struct page*)skb;
++                      frag_info.length = skb_tailroom(skb);
++                      frag_info.phys_adr = dma_map_single(0, skb->tail, frag_info.length, DMA_FROM_DEVICE);
++                      BUG_ON(dma_mapping_error(frag_info.phys_adr));
 +
-+        // MMC, PMT and GLI interrupts are not masked by the interrupt enable
-+        // register, so must deal with them on the raw status
-+        if (unlikely(raw_status & ((1UL << DMA_STATUS_GPI_BIT) |
-+                                   (1UL << DMA_STATUS_GMI_BIT) |
-+                                   (1UL << DMA_STATUS_GLI_BIT))))  {
-+            process_non_dma_ints(raw_status);
-+        }
++                      // Associate the skb with the descriptor
++                      desc = set_rx_descriptor(priv, &frag_info);
++                      if (desc >= 0) {
++                              filled = 1;
++                      } else {
++                              // No, so release the DMA mapping for the socket buffer
++                              dma_unmap_single(0, frag_info.phys_adr, frag_info.length, DMA_FROM_DEVICE);
 +
-+        // Get status of enabled interrupt sources.
-+        status = raw_status & int_enable;
-+    }
++                              // Free the socket buffer
++                              dev_kfree_skb(skb);
 +
-+    return IRQ_HANDLED;
-+}
-+#endif // CONFIG_LEON_COPRO 
++                              // No more RX descriptor ring entries to refill
++                              break;
++                      }
++              }
++      }
 +
-+#ifdef CONFIG_LEON_COPRO
-+static struct semaphore copro_stop_semaphore;
++#ifndef CONFIG_HIPOX_VERSION_0X800
++      if (likely(filled)) {
++              // Issue a RX poll demand to restart RX descriptor processing and DFF
++              // mode does not automatically restart descriptor processing after a
++              // descriptor unavailable event
++              dma_reg_write(priv, DMA_RX_POLL_REG, 0);
++      }
++#endif // !CONFIG_HIPOX_VERSION_0X800
++}
 +
-+static void copro_stop_callback(volatile gmac_cmd_que_ent_t* entry)
++static inline void set_phy_type_rgmii(void)
 +{
-+    up(&copro_stop_semaphore);
++#ifndef CONFIG_HIPOX_VERSION_0X800
++      // Use sysctrl to switch MAC link lines into either (G)MII or RGMII mode
++      u32 reg_contents = readl(SYS_CTRL_GMAC_CTRL);
++      reg_contents |= (1UL << SYS_CTRL_GMAC_RGMII);
++    writel(reg_contents, SYS_CTRL_RSTEN_SET_CTRL);
++#endif // !CONFIG_HIPOX_VERSION_0X800
 +}
-+#endif // CONFIG_LEON_COPRO
 +
-+static void gmac_down(struct net_device *dev)
++static void initialise_phy(gmac_priv_t* priv)
 +{
-+    gmac_priv_t* priv = (gmac_priv_t*)netdev_priv(dev);
-+    int desc;
-+    u32 int_enable;
-+#ifdef CONFIG_LEON_COPRO
-+    tx_que_t *tx_queue = &priv->tx_queue_;
-+    int cmd_queue_result;
-+#endif // CONFIG_LEON_COPRO
++      switch (priv->phy_type) {
++              case PHY_TYPE_VITESSE_VSC8201XVZ:
++                      {
++                              // Allow s/w to override mode/duplex pin settings
++                              u32 acsr = priv->mii.mdio_read(priv->netdev, priv->mii.phy_id, VSC8201_MII_ACSR);
 +
-+      // Stop NAPI
-+      napi_disable(&priv->napi_struct);
++                              printk(KERN_INFO "%s: PHY is Vitesse VSC8201XVZ\n", priv->netdev->name);
++                              acsr |= (1UL << VSC8201_MII_ACSR_MDPPS_BIT);
++                              priv->mii.mdio_write(priv->netdev, priv->mii.phy_id, VSC8201_MII_ACSR, acsr);
++                      }
++                      break;
++              case PHY_TYPE_REALTEK_RTL8211BGR:
++                      printk(KERN_INFO "%s: PHY is Realtek RTL8211BGR\n", priv->netdev->name);
++                      set_phy_type_rgmii();
++                      break;
++              case PHY_TYPE_LSI_ET1011C:
++              case PHY_TYPE_LSI_ET1011C2:
++                      {
++                              u32 phy_reg;
 +
-+    // Stop further TX packets being delivered to hard_start_xmit();
-+    netif_stop_queue(dev);
-+    netif_carrier_off(dev);
++                              printk(KERN_INFO "%s: PHY is LSI ET1011C\n", priv->netdev->name);
 +
-+    // Disable all GMAC interrupts and wait for change to be acknowledged
-+    gmac_int_en_clr(priv, ~0UL, &int_enable, 0);
++                              // Configure clocks
++                              phy_reg = priv->mii.mdio_read(priv->netdev, priv->mii.phy_id, ET1011C_MII_CONFIG);
++                              phy_reg &= ~(((1UL << ET1011C_MII_CONFIG_IFMODESEL_NUM_BITS) - 1) << ET1011C_MII_CONFIG_IFMODESEL);
++                              phy_reg |= (ET1011C_MII_CONFIG_IFMODESEL_GMII_MII << ET1011C_MII_CONFIG_IFMODESEL);
++                              phy_reg |= ((1UL << ET1011C_MII_CONFIG_SYSCLKEN) |
++                              (1UL << ET1011C_MII_CONFIG_TXCLKEN) |
++                                                         (1UL << ET1011C_MII_CONFIG_TBI_RATESEL) |
++                                                         (1UL << ET1011C_MII_CONFIG_CRS_TX_EN));
++                              priv->mii.mdio_write(priv->netdev, priv->mii.phy_id, ET1011C_MII_CONFIG, phy_reg);
 +
-+#ifdef CONFIG_LEON_COPRO
-+    // Tell the CoPro to stop network offload operations
-+    cmd_queue_result = -1;
-+    while (cmd_queue_result) {
-+        spin_lock(&priv->cmd_que_lock_);
-+        cmd_queue_result = cmd_que_queue_cmd(&priv->cmd_queue_, GMAC_CMD_STOP, 0, copro_stop_callback);
-+        spin_unlock(&priv->cmd_que_lock_);
-+    }
++                              // Enable Tx/Rx LED
++                              phy_reg = priv->mii.mdio_read(priv->netdev, priv->mii.phy_id, ET1011C_MII_LED2);
++                              phy_reg &= ~(((1UL << ET1011C_MII_LED2_LED_NUM_BITS) - 1) << ET1011C_MII_LED2_LED_TXRX);
++                              phy_reg |= (ET1011C_MII_LED2_LED_TXRX_ACTIVITY << ET1011C_MII_LED2_LED_TXRX);
++                              priv->mii.mdio_write(priv->netdev, priv->mii.phy_id, ET1011C_MII_LED2, phy_reg);
++                      }
++                      break;
++              case PHY_TYPE_ICPLUS_IP1001:
++                      printk(KERN_INFO "%s: PHY is ICPlus 1001\n", priv->netdev->name);
++                      break;
++      }
++}
 +
-+    // Interrupt the CoPro so it sees the new command
-+    writel(1UL << COPRO_SEM_INT_CMD, SYS_CTRL_SEMA_SET_CTRL);
++static struct kobj_type ktype_gmac_link_state = {
++      .release = 0,
++      .sysfs_ops = 0,
++      .default_attrs = 0,
++};
 +
-+    // Wait until the CoPro acknowledges the STOP command
-+    down_interruptible(&copro_stop_semaphore);
++static int gmac_link_state_hotplug_filter(struct kset* kset, struct kobject* kobj) {
++      return get_ktype(kobj) == &ktype_gmac_link_state;
++}
 +
-+    // Wait until the CoPro acknowledges that it has completed stopping
-+    down_interruptible(&priv->copro_stop_complete_semaphore_);
++static const char* gmac_link_state_hotplug_name(struct kset* kset, struct kobject* kobj) {
++      return "gmac_link_state";
++}
 +
-+    // Clear out the Tx offload job queue, deallocating associated resources
-+    while (tx_que_not_empty(tx_queue)) {
-+        // Free any dynamic fragment ptr/len storage
-+        /** @todo */
-+        tx_que_inc_r_ptr(tx_queue);
-+    }
++static struct kset_uevent_ops gmac_link_state_uevent_ops = {
++      .filter = gmac_link_state_hotplug_filter,
++      .name   = gmac_link_state_hotplug_name,
++      .uevent = NULL,
++};
 +
-+    // Reinitialise the Tx offload queue metadata
-+    tx_que_init(
-+        &priv->tx_queue_,
-+        (gmac_tx_que_ent_t*)descriptors_phys_to_virt(priv->copro_params_.tx_que_head_),
-+        priv->copro_tx_que_num_entries_);
++static int gmac_link_state_init_sysfs(gmac_priv_t* priv)
++{
++      int err = 0;
++
++      /* Prepare the sysfs interface for use */
++      kobject_set_name(&priv->link_state_kset.kobj, "gmac_link_state");
++      priv->link_state_kset.ktype = &ktype_gmac_link_state;
++
++      err = subsystem_register(&priv->link_state_kset);
++      if (err)
++              return err;
++
++      /* Setup hotplugging */
++      priv->link_state_kset.uevent_ops = &gmac_link_state_uevent_ops;
 +
-+    // Empty the pending SKB queue
-+    while (!list_empty(&priv->copro_tx_skb_list_)) {
-+        struct sk_buff *skb;
++      /* Setup the heirarchy, the name will be set on detection */
++      kobject_init(&priv->link_state_kobject);
++      priv->link_state_kobject.kset = kset_get(&priv->link_state_kset);
++      priv->link_state_kobject.parent = &priv->link_state_kset.kobj;
 +
-+        // Remove the first entry on the list
-+        struct list_head *entry = priv->copro_tx_skb_list_.next;
-+        BUG_ON(!entry);
-+        list_del(entry);
++      /* Build the sysfs entry */
++      kobject_set_name(&priv->link_state_kobject, "gmac_link_state-1");
++      return kobject_add(&priv->link_state_kobject);
++}
 +
-+        // Get pointer to SKB from it's list_head member
-+        skb = list_entry(entry, struct sk_buff, cb);
-+        BUG_ON(!skb);
++static void work_handler(struct work_struct *ws) {
++      gmac_priv_t *priv = container_of(ws, gmac_priv_t, link_state_change_work);
 +
-+        // Inform the network stack that we've finished with the packet
-+        dev_kfree_skb(skb);
-+    }
-+    priv->copro_tx_skb_list_count_ =  0;
-+#endif // CONFIG_LEON_COPRO
++      kobject_uevent(&priv->link_state_kobject, priv->link_state ? KOBJ_ONLINE : KOBJ_OFFLINE);
++}
 +
-+#ifndef CONFIG_LEON_OFFLOAD_TX
-+    // Stop transmitter, take ownership of all tx descriptors
-+    dma_reg_clear_mask(priv, DMA_OP_MODE_REG, 1UL << DMA_OP_MODE_ST_BIT);
-+    if (priv->desc_vaddr) {
-+        tx_take_ownership(&priv->tx_gmac_desc_list_info);
-+    }
-+#endif // !CONFIG_LEON_OFFLOAD_TX
++static void link_state_change_callback(
++      int   link_state,
++      void *arg)
++{
++      gmac_priv_t* priv = (gmac_priv_t*)arg;
 +
-+    // Stop receiver, waiting until it's really stopped and then take ownership
-+    // of all rx descriptors
-+    change_rx_enable(priv, 0, 1, 0);
++      priv->link_state = link_state;
++      schedule_work(&priv->link_state_change_work);
++}
 +
-+    if (priv->desc_vaddr) {
-+        rx_take_ownership(&priv->rx_gmac_desc_list_info);
-+    }
++static void start_watchdog_timer(gmac_priv_t* priv)
++{
++    priv->watchdog_timer.expires = jiffies + WATCHDOG_TIMER_INTERVAL;
++    priv->watchdog_timer_shutdown = 0;
++    mod_timer(&priv->watchdog_timer, priv->watchdog_timer.expires);
++}
 +
-+    // Stop all timers
-+    delete_watchdog_timer(priv);
++static void delete_watchdog_timer(gmac_priv_t* priv)
++{
++    // Ensure link/PHY state watchdog timer won't be invoked again
++    priv->watchdog_timer_shutdown = 1;
++    del_timer_sync(&priv->watchdog_timer);
++}
 +
-+    if (priv->desc_vaddr) {
-+        // Free receive descriptors
-+        do {
-+            int first_last = 0;
-+            rx_frag_info_t frag_info;
++static inline int is_auto_negotiation_in_progress(gmac_priv_t* priv)
++{
++    return !(phy_read(priv->netdev, priv->phy_addr, MII_BMSR) & BMSR_ANEGCOMPLETE);
++}
 +
-+            desc = get_rx_descriptor(priv, &first_last, 0, &frag_info);
-+            if (desc >= 0) {
-+                              if (unlikely(priv->rx_buffers_per_page)) {
-+                                      // If this is the last packet in the page, release the DMA mapping
-+                                      unmap_rx_page(priv, frag_info.phys_adr);
-+                                      put_page(frag_info.page);
-+                              } else {
-+                    // Release the DMA mapping for the packet buffer
-+                    dma_unmap_single(0, frag_info.phys_adr, frag_info.length, DMA_FROM_DEVICE);
++static void watchdog_timer_action(unsigned long arg)
++{
++    typedef enum watchdog_state {
++        WDS_IDLE,
++        WDS_RESETTING,
++        WDS_NEGOTIATING
++    } watchdog_state_t;
 +
-+                    // Free the skb
-+                    dev_kfree_skb((struct sk_buff *)frag_info.page);
-+                              }
-+            }
-+        } while (desc >= 0);
++    static int state = WDS_IDLE;
 +
-+        // Free transmit descriptors
-+        do {
-+            struct sk_buff *skb;
-+            tx_frag_info_t  frag_info;
-+            int             buffer_owned;
++    gmac_priv_t* priv = (gmac_priv_t*)arg;
++    unsigned long new_timeout = jiffies + WATCHDOG_TIMER_INTERVAL;
++#ifndef ARMULATING
++    int ready;
++    int duplex_changed;
++    int gigabit_changed;
++    int pause_changed;
 +
-+            desc = get_tx_descriptor(priv, &skb, 0, &frag_info, &buffer_owned);
-+            if (desc >= 0) {
-+                if (buffer_owned) {
-+                    // Release the DMA mapping for the packet buffer
-+                    dma_unmap_single(0, frag_info.phys_adr, frag_info.length, DMA_FROM_DEVICE);
-+                }
++      // Interpret the PHY/link state.
++      if (priv->phy_force_negotiation || (state == WDS_RESETTING)) {
++              mii_check_link(&priv->mii);
++              ready = 0;
++      } else {
++              duplex_changed = mii_check_media_ex(&priv->mii, 1, priv->mii_init_media, &gigabit_changed, &pause_changed, link_state_change_callback, priv);
++              priv->mii_init_media = 0;
++              ready = netif_carrier_ok(priv->netdev);
++      }
 +
-+                if (skb) {
-+                    // Free the skb
-+                    dev_kfree_skb(skb);
-+                }
++    if (!ready) {
++        if (priv->phy_force_negotiation) {
++            if (netif_carrier_ok(priv->netdev)) {
++                state = WDS_RESETTING;
++            } else {
++                state = WDS_IDLE;
 +            }
-+        } while (desc >= 0);
 +
-+        // Free any resources associated with the buffers of a pending packet
-+        if (priv->tx_pending_fragment_count) {
-+            tx_frag_info_t *frag_info = priv->tx_pending_fragments;
++            priv->phy_force_negotiation = 0;
++        }
 +
-+            while (priv->tx_pending_fragment_count--) {
-+                dma_unmap_single(0, frag_info->phys_adr, frag_info->length, DMA_FROM_DEVICE);
-+                ++frag_info;
++        // May be a good idea to restart everything here, in an attempt to clear
++        // out any fault conditions
++        if ((state == WDS_NEGOTIATING) && is_auto_negotiation_in_progress(priv)) {
++            new_timeout = jiffies + AUTO_NEG_INTERVAL;
++        } else {
++            switch (state) {
++                case WDS_IDLE:
++                    // Reset the PHY to get it into a known state
++                    start_phy_reset(priv);
++                    new_timeout = jiffies + START_RESET_INTERVAL;
++                    state = WDS_RESETTING;
++                    break;
++                case WDS_RESETTING:
++                    if (!is_phy_reset_complete(priv)) {
++                        new_timeout = jiffies + RESET_INTERVAL;
++                    } else {
++                        // Force or auto-negotiate PHY mode
++                        set_phy_negotiate_mode(priv->netdev);
++
++                        // Set PHY specfic features
++                        initialise_phy(priv);
++
++                        state = WDS_NEGOTIATING;
++                        new_timeout = jiffies + AUTO_NEG_INTERVAL;
++                    }
++                    break;
++                default:
++                    DBG(1, KERN_ERR "watchdog_timer_action() %s: Unexpected state\n", priv->netdev->name);
++                    state = WDS_IDLE;
++                    break;
 +            }
 +        }
++    } else {
++        state = WDS_IDLE;
++        if (duplex_changed) {
++            priv->mii.full_duplex ? mac_reg_set_mask(priv,   MAC_CONFIG_REG, (1UL << MAC_CONFIG_DM_BIT)) :
++                                    mac_reg_clear_mask(priv, MAC_CONFIG_REG, (1UL << MAC_CONFIG_DM_BIT));
++        }
 +
-+        // Free the socket buffer of a pending packet
-+        if (priv->tx_pending_skb) {
-+            dev_kfree_skb(priv->tx_pending_skb);
-+            priv->tx_pending_skb = 0;
++        if (gigabit_changed) {
++            change_gig_mode(priv);
 +        }
++
++              if (pause_changed) {
++                      change_pause_mode(priv);
++              }
 +    }
++#endif // !ARMULATING
 +
-+    // Power down the PHY
-+    phy_powerdown(dev);
++    // Re-trigger the timer, unless some other thread has requested it be stopped
++    if (!priv->watchdog_timer_shutdown) {
++        // Restart the timer
++        mod_timer(&priv->watchdog_timer, new_timeout);
++    }
 +}
 +
-+static int stop(struct net_device *dev)
++static int inline is_ip_packet(unsigned short eth_protocol)
 +{
-+    gmac_priv_t* priv = (gmac_priv_t*)netdev_priv(dev);
-+
-+    gmac_down(dev);
++    return (eth_protocol == ETH_P_IP)
++#ifdef SUPPORT_IPV6
++              || (eth_protocol == ETH_P_IPV6)
++#endif // SUPPORT_IPV6
++              ;
++}
 +
-+#ifdef CONFIG_LEON_COPRO
-+    shutdown_copro();
++static int inline is_ipv4_packet(unsigned short eth_protocol)
++{
++    return eth_protocol == ETH_P_IP;
++}
 +
-+    if (priv->shared_copro_params_) {
-+        // Free the DMA coherent parameter space
-+        dma_free_coherent(0, sizeof(copro_params_t), priv->shared_copro_params_, priv->shared_copro_params_pa_);
-+        priv->shared_copro_params_ = 0;
-+    }
++#ifdef SUPPORT_IPV6
++static int inline is_ipv6_packet(unsigned short eth_protocol)
++{
++    return eth_protocol == ETH_P_IPV6;
++}
++#endif // SUPPORT_IPV6
 +
-+    // Disable semaphore register from causing ARM interrupts
-+    *((volatile unsigned long*)SYS_CTRL_SEMA_MASKA_CTRL) = 0;
-+    *((volatile unsigned long*)SYS_CTRL_SEMA_MASKB_CTRL) = 0;
++static int inline is_hw_checksummable(unsigned short protocol)
++{
++    return (protocol == IPPROTO_TCP) || (protocol == IPPROTO_UDP)
++#ifndef CONFIG_HIPOX_VERSION_0X800
++           || (protocol == IPPROTO_ICMP)
++#endif // !CONFIG_HIPOX_VERSION_0X800
++           ;
++}
 +
-+    // Release interrupts lines used by semaphore register interrupts
-+    if (priv->copro_a_irq_alloced_) {
-+        free_irq(priv->copro_a_irq_, dev);
-+        priv->copro_a_irq_alloced_ = 0;
-+    }
-+    if (priv->copro_b_irq_alloced_) {
-+        free_irq(priv->copro_b_irq_, dev);
-+        priv->copro_b_irq_alloced_ = 0;
-+    }
-+#endif // CONFIG_LEON_COPRO 
++static u32 unmap_rx_page(
++      gmac_priv_t *priv,
++      dma_addr_t   phys_adr)
++{
++      u32 offset = phys_adr & ~PAGE_MASK;
++      u32 next_offset = offset + priv->rx_buffer_size_;
++      next_offset = SKB_DATA_ALIGN(next_offset);
++      next_offset += NET_IP_ALIGN;
 +
-+      // Free the shadow descriptor memory
-+      kfree(priv->tx_desc_shadow_);
-+      priv->tx_desc_shadow_ = 0;
++      // If this is the last packet in a page
++      if (next_offset > GMAC_ALLOC_SIZE) {
++              // Release the DMA mapping for the page
++              dma_unmap_page(0, phys_adr & PAGE_MASK, GMAC_ALLOC_SIZE, DMA_FROM_DEVICE);
++      }
 +
-+      kfree(priv->rx_desc_shadow_);
-+      priv->rx_desc_shadow_ = 0;
++      return offset;
++}
 +
-+    // Release the IRQ
-+    if (priv->have_irq) {
-+        free_irq(dev->irq, dev);
-+        priv->have_irq = 0;
-+    }
++#define FCS_LEN 4             // Ethernet CRC length
++#ifdef CONFIG_HIPOX_VERSION_0X800
++#define HW_CSUM_LEN 2 // The OX800 H/W appending partial csum length
++#endif // CONFIG_HIPOX_VERSION_0X800
 +
-+    // Disable the clock to the MAC block
-+    writel(1UL << SYS_CTRL_CKEN_MAC_BIT, SYS_CTRL_CKEN_CLR_CTRL);
++static inline int get_desc_len(
++      u32 desc_status,
++      int last)
++{
++      int length = get_rx_length(desc_status);
 +
-+      // Free the sysfs resources
-+      kobject_del(&priv->link_state_kobject);
-+      subsystem_unregister(&priv->link_state_kset);
++      if (last) {
++              length -= FCS_LEN;
++#if defined(CONFIG_HIPOX_VERSION_0X800) && defined(USE_RX_CSUM)
++          length -= HW_CSUM_LEN;
++#endif // CONFIG_HIPOX_VERSION_0X800 && USE_RX_CSUM
++      }
 +
-+    return 0;
++      return length;
 +}
 +
-+static void hw_set_mac_address(struct net_device *dev, unsigned char* addr)
++static int process_rx_packet_skb(gmac_priv_t *priv)
 +{
-+    u32 mac_lo;
-+    u32 mac_hi;
++      int             desc;
++      int             last;
++      u32             desc_status = 0;
++      rx_frag_info_t  frag_info;
++      int             packet_len;
++      struct sk_buff *skb;
++      int             valid;
++      int             ip_summed;
 +
-+    mac_lo  =  (u32)addr[0];
-+    mac_lo |= ((u32)addr[1] << 8);
-+    mac_lo |= ((u32)addr[2] << 16);
-+    mac_lo |= ((u32)addr[3] << 24);
++      desc = get_rx_descriptor(priv, &last, &desc_status, &frag_info);
++      if (desc < 0) {
++              return 0;
++      }
 +
-+    mac_hi  =  (u32)addr[4];
-+    mac_hi |= ((u32)addr[5] << 8);
++      // Release the DMA mapping for the received data
++    dma_unmap_single(0, frag_info.phys_adr, frag_info.length, DMA_FROM_DEVICE);
 +
-+    mac_reg_write(netdev_priv(dev), MAC_ADR0_LOW_REG, mac_lo);
-+    mac_reg_write(netdev_priv(dev), MAC_ADR0_HIGH_REG, mac_hi);
-+}
++      // Get the packet data length
++      packet_len = get_desc_len(desc_status, last);
 +
-+static int set_mac_address(struct net_device *dev, void *p)
-+{
-+    struct sockaddr *addr = p;
++      // Get pointer to the SKB
++      skb = (struct sk_buff*)frag_info.page;
 +
-+    if (!is_valid_ether_addr(addr->sa_data)) {
-+        return -EADDRNOTAVAIL;
-+    }
++      // Is the packet entirely contained within the descriptors and without errors?
++      valid = !(desc_status & (1UL << RDES0_ES_BIT));
 +
-+    memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
-+    hw_set_mac_address(dev, addr->sa_data);
++      if (unlikely(!valid)) {
++              goto not_valid_skb;
++      }
 +
-+    return 0;
-+}
++      ip_summed = CHECKSUM_NONE;
 +
-+static void multicast_hash(struct dev_mc_list *dmi, u32 *hash_lo, u32 *hash_hi)
-+{
-+    u32 crc = ether_crc_le(dmi->dmi_addrlen, dmi->dmi_addr);
-+    u32 mask = 1 << ((crc >> 26) & 0x1F);
++#ifdef USE_RX_CSUM
++      // Has the h/w flagged an IP header checksum failure?
++      valid = !(desc_status & (1UL << RDES0_IPC_BIT));
 +
-+    if (crc >> 31) {
-+        *hash_hi |= mask;
-+    } else {
-+        *hash_lo |= mask;
-+    }
-+}
++      if (likely(valid)) {
++              // Determine whether Ethernet frame contains an IP packet -
++              // only bother with Ethernet II frames, but do cope with
++              // 802.1Q VLAN tag presence
++              int vlan_offset = 0;
++              unsigned short eth_protocol = ntohs(((struct ethhdr*)skb->data)->h_proto);
++              int is_ip = is_ip_packet(eth_protocol);
 +
-+static void set_multicast_list(struct net_device *dev)
-+{
-+    gmac_priv_t* priv = netdev_priv(dev);
-+    u32 hash_lo=0;
-+    u32 hash_hi=0;
-+    u32 mode = 0;
-+    int i;
++              if (!is_ip) {
++                      // Check for VLAN tag
++                      if (eth_protocol == ETH_P_8021Q) {
++                              // Extract the contained protocol type from after
++                              // the VLAN tag
++                              eth_protocol = ntohs(*(unsigned short*)(skb->data + ETH_HLEN));
++                              is_ip = is_ip_packet(eth_protocol);
 +
-+    // Disable promiscuous mode and uni/multi-cast matching
-+    mac_reg_write(priv, MAC_FRAME_FILTER_REG, mode);
++                              // Adjustment required to skip the VLAN stuff and
++                              // get to the IP header
++                              vlan_offset = 4;
++                      }
++              }
 +
-+    // Disable all perfect match registers
-+    for (i=0; i < NUM_PERFECT_MATCH_REGISTERS; ++i) {
-+        mac_adrhi_reg_write(priv, i, 0);
-+    }
++              // Only offload checksum calculation for IP packets
++              if (is_ip) {
++#ifdef CONFIG_HIPOX_VERSION_0X800
++                      u16 payload_length = 0;
++#endif // CONFIG_HIPOX_VERSION_0X800
++                      struct iphdr* ipv4_header = 0;
 +
-+    // Promiscuous mode overrides all-multi which overrides other filtering
-+    if (dev->flags & IFF_PROMISC) {
-+        mode |= (1 << MAC_FRAME_FILTER_PR_BIT);
-+    } else if (dev->flags & IFF_ALLMULTI) {
-+        mode |= (1 << MAC_FRAME_FILTER_PM_BIT);
-+    } else {
-+        struct dev_mc_list *dmi;
++#ifndef CONFIG_HIPOX_VERSION_0X800
++                      if (unlikely(desc_status & (1UL << RDES0_PCE_BIT))) {
++                              valid = 0;
++                      } else
++#endif // !CONFIG_HIPOX_VERSION_0X800
++                      if (is_ipv4_packet(eth_protocol)) {
++                              ipv4_header = (struct iphdr*)(skb->data + ETH_HLEN + vlan_offset);
 +
-+        if (dev->mc_count <= NUM_PERFECT_MATCH_REGISTERS) {
-+            // Use perfect matching registers
-+            for (i=0, dmi = dev->mc_list; dmi; dmi = dmi->next, ++i) {
-+                u32 addr;
++                              // H/W can only checksum non-fragmented IP packets
++                              if (!(ipv4_header->frag_off & htons(IP_MF | IP_OFFSET))) {
++#ifdef CONFIG_HIPOX_VERSION_0X800
++                                      switch (ipv4_header->protocol) {
++                                              case IPPROTO_TCP:
++                                                      // Compute TCP pseudo-header checksum
++                                                      payload_length = ntohs(ipv4_header->tot_len) - (ipv4_header->ihl*4);
++                                                      break;
++                                              case IPPROTO_UDP:
++                                                      {
++                                                              struct udphdr* udp_header = (struct udphdr*)((u8*)ipv4_header + (ipv4_header->ihl*4));
++                                                              payload_length = ntohs(udp_header->len);
++                                                      }
++                                                      break;
++                                              default:
++                                                      // Not supporting any other than TCP/UDP
++                                                      break;
++                                      }
++#else // CONFIG_HIPOX_VERSION_0X800
++                              if (is_hw_checksummable(ipv4_header->protocol)) {
++                                      ip_summed = CHECKSUM_UNNECESSARY;
++                              }
++#endif // CONFIG_HIPOX_VERSION_0X800
++                              }
++                      }
++#ifndef CONFIG_HIPOX_VERSION_0X800
++                       else {
++#ifdef SUPPORT_IPV6
++                              struct ipv6hdr* ipv6_header = (struct ipv6hdr*)(skb->data + ETH_HLEN + vlan_offset);
 +
-+                addr  =      dmi->dmi_addr[0];
-+                addr |= (u32)dmi->dmi_addr[1] << 8;
-+                addr |= (u32)dmi->dmi_addr[2] << 16;
-+                addr |= (u32)dmi->dmi_addr[3] << 24;
-+                mac_adrlo_reg_write(priv, i, addr);
++                              if (is_hw_checksummable(ipv6_header->nexthdr)) {
++                                      ip_summed = CHECKSUM_UNNECESSARY;
++                              }
++#endif // SUPPORT_IPV6
++                      }
++#endif // !CONFIG_HIPOX_VERSION_0X800
 +
-+                addr  =      dmi->dmi_addr[4];
-+                addr |= (u32)dmi->dmi_addr[5] << 8;
-+                addr |= (1 << MAC_ADR1_HIGH_AE_BIT);
-+                mac_adrhi_reg_write(priv, i, addr);
-+            }
-+        } else {
-+            // Use hashing
-+            mode |= (1 << MAC_FRAME_FILTER_HUC_BIT);
-+            mode |= (1 << MAC_FRAME_FILTER_HMC_BIT);
++#ifdef CONFIG_HIPOX_VERSION_0X800
++                      if (payload_length) {
++                              // Get the hardware generated payload checksum from
++                              // the end of the received packet, reverse the 1's
++                              // complement operation that the h/w applies and add
++                              // to the pseudo-header checksum, in network order
++                              u16 hw_csum = ~(*(u16*)(skb->data + packet_len + FCS_LEN));
++
++                              // Calculate checksum of pseudo header and payload
++                              if (csum_tcpudp_magic(
++                                              ipv4_header->saddr,
++                                              ipv4_header->daddr,
++                                              payload_length,
++                                              ipv4_header->protocol,
++                                              hw_csum)) {
++                                      // Bad checksum, so indicate in descriptor status
++                                      desc_status |= (1UL << RDES0_IPC_BIT);
++                                      valid = 0;
++                              } else {
++                                      ip_summed = CHECKSUM_UNNECESSARY;
++                              }
++                      }
++#endif // CONFIG_HIPOX_VERSION_0X800
++              }
++      }
++
++      if (unlikely(!valid)) {
++              goto not_valid_skb;
++      }
++#endif // USE_RX_CSUM
++
++      // Increase the skb's data pointer to account for the RX packet that has
++      // been DMAed into it
++      skb_put(skb, packet_len);
++
++      // Set the device for the skb
++      skb->dev = priv->netdev;
++
++      // Set packet protocol
++      skb->protocol = eth_type_trans(skb, priv->netdev);
++
++      // Record whether h/w checksumed the packet
++      skb->ip_summed = ip_summed;
++
++      // Send the packet up the network stack
++      netif_receive_skb(skb);
++
++      // Update receive statistics
++      priv->netdev->last_rx = jiffies;
++      ++priv->stats.rx_packets;
++      priv->stats.rx_bytes += packet_len;
++
++      return 1;
++
++not_valid_skb:
++      dev_kfree_skb(skb);
 +
-+            for (dmi = dev->mc_list; dmi; dmi = dmi->next) {
-+                multicast_hash(dmi, &hash_lo, &hash_hi);
-+            }
-+        }
-+    }
++      DBG(2, KERN_WARNING "process_rx_packet() %s: Received packet has bad desc_status = 0x%08x\n", priv->netdev->name, desc_status);
 +
-+    // Update the filtering rules
-+    mac_reg_write(priv, MAC_FRAME_FILTER_REG, mode);
++      // Update receive statistics from the descriptor status
++      if (is_rx_collision_error(desc_status)) {
++              DBG(20, KERN_INFO "process_rx_packet() %s: Collision (0x%08x:%u bytes)\n", priv->netdev->name, desc_status, desc_len);
++              ++priv->stats.collisions;
++      }
++      if (is_rx_crc_error(desc_status)) {
++              DBG(20, KERN_INFO "process_rx_packet() %s: CRC error (0x%08x:%u bytes)\n", priv->netdev->name, desc_status, desc_len);
++              ++priv->stats.rx_crc_errors;
++              ++priv->stats.rx_errors;
++      }
++      if (is_rx_frame_error(desc_status)) {
++              DBG(20, KERN_INFO "process_rx_packet() %s: frame error (0x%08x:%u bytes)\n", priv->netdev->name, desc_status, desc_len);
++              ++priv->stats.rx_frame_errors;
++              ++priv->stats.rx_errors;
++      }
++      if (is_rx_length_error(desc_status)) {
++              DBG(20, KERN_INFO "process_rx_packet() %s: Length error (0x%08x:%u bytes)\n", priv->netdev->name, desc_status, desc_len);
++              ++priv->stats.rx_length_errors;
++              ++priv->stats.rx_errors;
++      }
++      if (is_rx_csum_error(desc_status)) {
++              DBG(20, KERN_INFO "process_rx_packet() %s: Checksum error (0x%08x:%u bytes)\n", priv->netdev->name, desc_status, desc_len);
++              ++priv->stats.rx_frame_errors;
++              ++priv->stats.rx_errors;
++      }
 +
-+    // Update the filtering hash table
-+    mac_reg_write(priv, MAC_HASH_LOW_REG,  hash_lo);
-+    mac_reg_write(priv, MAC_HASH_HIGH_REG, hash_hi);
++      return 0;
 +}
 +
-+static int gmac_up(struct net_device *dev)
++static int process_rx_packet(gmac_priv_t *priv)
 +{
-+    int status = 0;
-+    gmac_priv_t *priv = (gmac_priv_t*)netdev_priv(dev);
-+    u32 reg_contents;
-+#ifdef CONFIG_LEON_COPRO
-+    int cmd_queue_result;
-+#endif // CONFIG_LEON_COPRO
++      struct sk_buff *skb = NULL;
++      int             last;
++      u32             desc_status;
++      rx_frag_info_t  frag_info;
++      int             desc;
++      u32             offset;
++      int             desc_len;
++      unsigned char  *packet;
++      int             valid;
++      int             desc_used = 0;
++      int             hlen = 0;
++      int             partial_len = 0;
++      int             first = 1;
 +
-+    // Reset the entire GMAC
-+    dma_reg_write(priv, DMA_BUS_MODE_REG, 1UL << DMA_BUS_MODE_SWR_BIT);
++      // Check that there is at least one Rx descriptor available. Cache the
++      // descriptor information so we don't have to touch the uncached/unbuffered
++      // descriptor memory more than necessary when we come to use that descriptor
++      if (!rx_available_for_read(&priv->rx_gmac_desc_list_info, &desc_status)) {
++              return 0;
++      }
 +
-+    // Ensure reset is performed before testing for completion
-+    wmb();
++      // Attempt to allocate an skb before we change anything on the Rx descriptor ring
++      skb = dev_alloc_skb(GMAC_HLEN + NET_IP_ALIGN);
++      if (unlikely(skb == NULL)) {
++              return 0;
++      }
 +
-+    // Wait for the reset operation to complete
-+    status = -EIO;
-+      printk(KERN_INFO "Resetting GMAC\n");
-+    for (;;) {
-+        if (!(dma_reg_read(priv, DMA_BUS_MODE_REG) & (1UL << DMA_BUS_MODE_SWR_BIT))) {
-+            status = 0;
-+            break;
-+        }
-+    }
++      // Align IP header start in header storage
++      skb_reserve(skb, NET_IP_ALIGN);
 +
-+    // Did the GMAC reset operation fail?
-+    if (status) {
-+        printk(KERN_ERR "open() %s: GMAC reset failed\n", dev->name);
-+        goto gmac_up_err_out;
-+    }
-+      printk(KERN_INFO "GMAC reset complete\n");
++      // Process all descriptors associated with the packet
++      while (1) {
++              int prev_len;
 +
-+      /* Initialise MAC config register contents
-+       */
-+    reg_contents = 0;
-+    if (!priv->mii.using_1000) {
-+        DBG(1, KERN_INFO "open() %s: PHY in 10/100Mb mode\n", dev->name);
-+        reg_contents |= (1UL << MAC_CONFIG_PS_BIT);
-+    } else {
-+        DBG(1, KERN_INFO "open() %s: PHY in 1000Mb mode\n", dev->name);
-+    }
-+    if (priv->mii.full_duplex) {
-+        reg_contents |= (1UL << MAC_CONFIG_DM_BIT);
-+    }
++              // First call to get_rx_descriptor() will use the status read from the
++              // first descriptor by the call to rx_available_for_read() above
++              while ((desc = get_rx_descriptor(priv, &last, &desc_status, &frag_info)) < 0) {
++                      // We are part way through processing a multi-descriptor packet
++                      // and the GMAC hasn't finished with the next descriptor for the
++                      // packet yet, so have to poll until it becomes available
++                      desc_status = 0;
++                      udelay(1);
++              }
 +
-+#ifdef USE_RX_CSUM
-+      reg_contents |= (1UL << MAC_CONFIG_IPC_BIT);
-+#endif // USE_RX_CSUM
++              // We've consumed a descriptor
++              ++desc_used;
 +
-+    if (priv->jumbo_) {
-+              // Allow passage of jumbo frames through both transmitter and receiver
-+              reg_contents |= ((1UL << MAC_CONFIG_JE_BIT) |
-+                        (1UL << MAC_CONFIG_JD_BIT) |
-+                                               (1UL << MAC_CONFIG_WD_BIT));
-+      }
++              if (!frag_info.page) {
++                      panic("process_rx_packet() %s: Found RX descriptor without attached page\n", priv->netdev->name);
++              }
 +
-+      // Enable transmitter and receiver
-+    reg_contents |= ((1UL << MAC_CONFIG_TE_BIT) |
-+                     (1UL << MAC_CONFIG_RE_BIT));
++              // If this is the last packet in the page, release the DMA mapping
++              offset = unmap_rx_page(priv, frag_info.phys_adr);
++              if (!first) {
++                      // The buffer adr of descriptors associate with middle or last
++                      // parts of a packet have ls 2 bits of buffer adr ignored by GMAC DMA
++                      offset &= ~0x3;
++              }
 +
-+      // Select the minimum IFG - I found that 80 bit times caused very poor
-+      // IOZone performance, so stcik with the 96 bit times default
-+      reg_contents |= (0UL << MAC_CONFIG_IFG_BIT);
++              // Get the length of the packet excluding CRC, h/w csum etc.
++              prev_len = partial_len;
++              partial_len = get_desc_len(desc_status, last);
++              desc_len = partial_len - prev_len;
 +
-+    // Write MAC config setup to the GMAC
-+    mac_reg_write(priv, MAC_CONFIG_REG, reg_contents);
++              // Get a pointer to the start of the packet data received into page
++              packet = page_address(frag_info.page) + offset;
 +
-+      /* Initialise MAC VLAN register contents
-+       */
-+    reg_contents = 0;
-+    mac_reg_write(priv, MAC_VLAN_TAG_REG, reg_contents);
++              // Is the packet entirely contained within the desciptors and without errors?
++              valid = !(desc_status & (1UL << RDES0_ES_BIT));
 +
-+    // Initialise the hardware's record of our primary MAC address
-+    hw_set_mac_address(dev, dev->dev_addr);
++              if (unlikely(!valid)) {
++                      goto not_valid;
++              }
 +
-+    // Initialise multicast and promiscuous modes
-+    set_multicast_list(dev);
++              if (first) {
++                      // Store headers in skb buffer
++                      hlen = min(GMAC_HLEN, desc_len);
 +
-+    // Disable all MMC interrupt sources
-+    mac_reg_write(priv, MMC_RX_MASK_REG, ~0UL);
-+    mac_reg_write(priv, MMC_TX_MASK_REG, ~0UL);
++                      // Copy header into skb buffer
++                      memcpy(skb->data, packet, hlen);
++                      skb->tail += hlen;
 +
-+    // Remember how large the unified descriptor array is to be
-+    priv->total_num_descriptors = NUM_TX_DMA_DESCRIPTORS + NUM_RX_DMA_DESCRIPTORS;
++                      if (desc_len > hlen) {
++                              // Point skb frags array at remaining packet data in pages
++                              skb_shinfo(skb)->nr_frags = 1;
++                              skb_shinfo(skb)->frags[0].page = frag_info.page;
++                              skb_shinfo(skb)->frags[0].page_offset = offset + hlen;
++                              skb_shinfo(skb)->frags[0].size = desc_len - hlen;
++                      } else {
++                              // Entire packet now in skb buffer so don't require page anymore
++                              put_page(frag_info.page);
++                      }
 +
-+    // Initialise the structures managing the TX descriptor list
-+    init_tx_desc_list(&priv->tx_gmac_desc_list_info,
-+                      priv->desc_vaddr,
-+                      priv->tx_desc_shadow_,
-+                      NUM_TX_DMA_DESCRIPTORS);
++                      first = 0;
++              } else {
++                      // Store intermediate descriptor data into packet
++                      int frag_index = skb_shinfo(skb)->nr_frags;
++                      skb_shinfo(skb)->frags[frag_index].page = frag_info.page;
++                      skb_shinfo(skb)->frags[frag_index].page_offset = offset;
++                      skb_shinfo(skb)->frags[frag_index].size = desc_len;
++                      ++skb_shinfo(skb)->nr_frags;
++              }
 +
-+    // Initialise the structures managing the RX descriptor list
-+    init_rx_desc_list(&priv->rx_gmac_desc_list_info,
-+                      priv->desc_vaddr + NUM_TX_DMA_DESCRIPTORS,
-+                      priv->rx_desc_shadow_,
-+                      NUM_RX_DMA_DESCRIPTORS,
-+                      priv->rx_buffer_size_);
++              if (last) {
++                      int ip_summed = CHECKSUM_NONE;
 +
-+    // Reset record of pending Tx packet
-+    priv->tx_pending_skb = 0;
-+    priv->tx_pending_fragment_count = 0;
++                      // Update total packet length skb metadata
++                      skb->len = partial_len;
++                      skb->data_len = skb->len - hlen;
++                      skb->truesize = skb->len + sizeof(struct sk_buff);
 +
-+#ifndef CONFIG_LEON_OFFLOAD_TX
-+    // Write the physical DMA consistent address of the start of the tx descriptor array
-+    dma_reg_write(priv, DMA_TX_DESC_ADR_REG, priv->desc_dma_addr);
-+#endif // !CONFIG_LEON_OFFLOAD_TX
++#ifdef USE_RX_CSUM
++                      // Has the h/w flagged an IP header checksum failure?
++                      valid = !(desc_status & (1UL << RDES0_IPC_BIT));
 +
-+    // Write the physical DMA consistent address of the start of the rx descriptor array
-+    dma_reg_write(priv, DMA_RX_DESC_ADR_REG, priv->desc_dma_addr +
-+                        (priv->tx_gmac_desc_list_info.num_descriptors * sizeof(gmac_dma_desc_t)));
++                      // Are we offloading RX checksuming?
++                      if (likely(valid)) {
++                              // Determine whether Ethernet frame contains an IP packet -
++                              // only bother with Ethernet II frames, but do cope with
++                              // 802.1Q VLAN tag presence
++                              int vlan_offset = 0;
++                              unsigned short eth_protocol = ntohs(((struct ethhdr*)skb->data)->h_proto);
++                              int is_ip = is_ip_packet(eth_protocol);
 +
-+    // Initialise the GMAC DMA bus mode register
-+    dma_reg_write(priv, DMA_BUS_MODE_REG, ((1UL << DMA_BUS_MODE_FB_BIT)   |   // Force bursts
-+                                           (8UL << DMA_BUS_MODE_PBL_BIT)  |   // AHB burst size
-+                                           (1UL << DMA_BUS_MODE_DA_BIT)));    // Round robin Rx/Tx
++                              if (!is_ip) {
++                                      // Check for VLAN tag
++                                      if (eth_protocol == ETH_P_8021Q) {
++                                              // Extract the contained protocol type from after
++                                              // the VLAN tag
++                                              eth_protocol = ntohs(*(unsigned short*)(skb->data + ETH_HLEN));
++                                              is_ip = is_ip_packet(eth_protocol);
 +
-+    // Prepare receive descriptors
-+    refill_rx_ring(dev);
++                                              // Adjustment required to skip the VLAN stuff and
++                                              // get to the IP header
++                                              vlan_offset = 4;
++                                      }
++                              }
 +
-+    // Clear any pending interrupt requests
-+    dma_reg_write(priv, DMA_STATUS_REG, dma_reg_read(priv, DMA_STATUS_REG));
++                              // Only offload checksum calculation for IP packets
++                              if (is_ip) {
++#ifdef CONFIG_HIPOX_VERSION_0X800
++                                      u16 payload_length = 0;
++#endif // CONFIG_HIPOX_VERSION_0X800
++                                      struct iphdr* ipv4_header = 0;
 +
-+      /* Initialise flow control register contents
-+       */
-+      // Enable Rx flow control
-+    reg_contents = (1UL << MAC_FLOW_CNTL_RFE_BIT);
++#ifndef CONFIG_HIPOX_VERSION_0X800
++                                      if (unlikely(desc_status & (1UL << RDES0_PCE_BIT))) {
++                                              valid = 0;
++                                      } else
++#endif // !CONFIG_HIPOX_VERSION_0X800
++                                      if (is_ipv4_packet(eth_protocol)) {
++                                              ipv4_header = (struct iphdr*)(skb->data + ETH_HLEN + vlan_offset);
 +
++                                              // H/W can only checksum non-fragmented IP packets
++                                              if (!(ipv4_header->frag_off & htons(IP_MF | IP_OFFSET))) {
++#ifdef CONFIG_HIPOX_VERSION_0X800
++                                                      switch (ipv4_header->protocol) {
++                                                              case IPPROTO_TCP:
++                                                                      // Compute TCP pseudo-header checksum
++                                                                      payload_length = ntohs(ipv4_header->tot_len) - (ipv4_header->ihl*4);
++                                                                      break;
++                                                              case IPPROTO_UDP:
++                                                                      {
++                                                                              struct udphdr* udp_header = (struct udphdr*)((u8*)ipv4_header + (ipv4_header->ihl*4));
++                                                                              payload_length = ntohs(udp_header->len);
++                                                                      }
++                                                                      break;
++                                                              default:
++                                                                      // Not supporting any other than TCP/UDP
++                                                                      break;
++                                                      }
++#else // CONFIG_HIPOX_VERSION_0X800
++                                              if (is_hw_checksummable(ipv4_header->protocol)) {
++                                                      ip_summed = CHECKSUM_UNNECESSARY;
++                                              }
++#endif // CONFIG_HIPOX_VERSION_0X800
++                                              }
++                                      }
 +#ifndef CONFIG_HIPOX_VERSION_0X800
-+      if (priv->mii.using_pause) {
-+              // Enable Tx flow control
-+              reg_contents |= (1UL << MAC_FLOW_CNTL_TFE_BIT);
-+      }
++                                       else {
++#ifdef SUPPORT_IPV6
++                                              struct ipv6hdr* ipv6_header = (struct ipv6hdr*)(skb->data + ETH_HLEN + vlan_offset);
 +
-+    // Set the duration of the pause frames generated by the transmitter when
-+      // the Rx fifo fill threshold is exceeded
-+      reg_contents |= ((0x100UL << MAC_FLOW_CNTL_PT_BIT) |    // Pause for 256 slots
-+                                        (0x1UL << MAC_FLOW_CNTL_PLT_BIT));
++                                              if (is_hw_checksummable(ipv6_header->nexthdr)) {
++                                                      ip_summed = CHECKSUM_UNNECESSARY;
++                                              }
++#endif // SUPPORT_IPV6
++                                      }
 +#endif // !CONFIG_HIPOX_VERSION_0X800
 +
-+      // Write flow control setup to the GMAC
-+    mac_reg_write(priv, MAC_FLOW_CNTL_REG, reg_contents);
++#ifdef CONFIG_HIPOX_VERSION_0X800
++                                      if (payload_length) {
++                                              // Get the hardware generated payload checksum from
++                                              // the end of the received packet, reverse the 1's
++                                              // complement operation that the h/w applies and add
++                                              // to the pseudo-header checksum, in network order
++                                              u16 hw_csum = ~(*(u16*)(packet + desc_len + FCS_LEN));
 +
-+      /* Initialise operation mode register contents
-+       */
-+    // Initialise the GMAC DMA operation mode register. Set Tx/Rx FIFO thresholds
-+    // to make best use of our limited SDRAM bandwidth when operating in gigabit
-+      reg_contents = ((DMA_OP_MODE_TTC_256 << DMA_OP_MODE_TTC_BIT) |    // Tx threshold
-+                    (1UL << DMA_OP_MODE_FUF_BIT) |                                            // Forward Undersized good Frames
-+                    (DMA_OP_MODE_RTC_128 << DMA_OP_MODE_RTC_BIT) |    // Rx threshold 128 bytes
-+                    (1UL << DMA_OP_MODE_OSF_BIT));                                            // Operate on 2nd frame
++                                              // Calculate checksum of pseudo header and payload
++                                              if (csum_tcpudp_magic(
++                                                              ipv4_header->saddr,
++                                                              ipv4_header->daddr,
++                                                              payload_length,
++                                                              ipv4_header->protocol,
++                                                              hw_csum)) {
++                                                      // Bad checksum, so indicate in descriptor status
++                                                      desc_status |= (1UL << RDES0_IPC_BIT);
++                                                      valid = 0;
++                                              } else {
++                                                      ip_summed = CHECKSUM_UNNECESSARY;
++                                              }
++                                      }
++#endif // CONFIG_HIPOX_VERSION_0X800
++                              }
++                      }
 +
-+#ifndef CONFIG_HIPOX_VERSION_0X800
-+      // Enable hardware flow control
-+      reg_contents |= (1UL << DMA_OP_MODE_EFC_BIT);
++                      if (unlikely(!valid)) {
++                              goto not_valid;
++                      }
++#endif // USE_RX_CSUM
 +
-+      // Set threshold for enabling hardware flow control at (full-4KB) to give
-+      // space for upto two in-flight std MTU packets to arrive after pause frame
-+      // has been sent.
-+      reg_contents |= ((0UL << DMA_OP_MODE_RFA2_BIT) |
-+                                        (3UL << DMA_OP_MODE_RFA_BIT));
++                      // Initialise other required skb header fields
++                      skb->dev = priv->netdev;
++                      skb->protocol = eth_type_trans(skb, priv->netdev);
 +
-+      // Set threshold for disabling hardware flow control (-7KB)
-+      reg_contents |= ((1UL << DMA_OP_MODE_RFD2_BIT) |
-+                                        (2UL << DMA_OP_MODE_RFD_BIT));
++                      // Record whether h/w checksumed the packet
++                      skb->ip_summed = ip_summed;
 +
-+    // Don't flush Rx frames from FIFO just because there's no descriptor available
-+      reg_contents |= (1UL << DMA_OP_MODE_DFF_BIT);
-+#endif // !CONFIG_HIPOX_VERSION_0X800
++                      // Send the skb up the network stack
++                      netif_receive_skb(skb);
 +
-+      // Write settings to operation mode register
-+    dma_reg_write(priv, DMA_OP_MODE_REG, reg_contents);
++                      // Update receive statistics
++                      priv->netdev->last_rx = jiffies;
++                      ++priv->stats.rx_packets;
++                      priv->stats.rx_bytes += partial_len;
 +
-+#ifdef CONFIG_HIPOX_VERSION_0X800
-+    // Use store&forward when operating in gigabit mode, as OX800 does not have
-+    // sufficient SDRAM bandwidth to support gigabit Tx without it and OX800
-+      // does not support Tx checksumming in the GMAC
-+    if (priv->mii.using_1000) {
-+        dma_reg_set_mask(priv, DMA_OP_MODE_REG, (1UL << DMA_OP_MODE_SF_BIT));
-+    } else {
-+        dma_reg_clear_mask(priv, DMA_OP_MODE_REG, (1UL << DMA_OP_MODE_SF_BIT));
-+    }
-+#else // CONFIG_HIPOX_VERSION_0X800
-+    // GMAC requires store&forward in order to compute Tx checksums
-+    dma_reg_set_mask(priv, DMA_OP_MODE_REG, (1UL << DMA_OP_MODE_SF_BIT));
-+#endif // CONFIG_HIPOX_VERSION_0X800
++                      break;
++              }
 +
-+    // Ensure setup is complete, before enabling TX and RX
-+    wmb();
++              // Want next call to get_rx_descriptor() to read status from descriptor
++              desc_status = 0;
++      }
++    return desc_used;
 +
-+#ifdef CONFIG_LEON_COPRO
-+    // Update the CoPro's parameters with the current MTU
-+    priv->copro_params_.mtu_ = dev->mtu;
++not_valid:
++      if (!skb_shinfo(skb)->nr_frags) {
++              // Free the page as it wasn't attached to the skb
++              put_page(frag_info.page);
++      }
 +
-+    // Only attempt to write to uncached/unbuffered shared parameter storage if
-+    // CoPro is started and thus storage has been allocated
-+    if (priv->shared_copro_params_) {
-+        // Fill the CoPro parameter block
-+        memcpy(priv->shared_copro_params_, &priv->copro_params_, sizeof(copro_params_t));
-+    }
++      dev_kfree_skb(skb);
 +
-+    // Make sure the CoPro parameter block updates have made it to memory (which
-+    // is uncached/unbuffered, so just compiler issues to overcome)
-+    wmb();
++      DBG(2, KERN_WARNING "process_rx_packet() %s: Received packet has bad desc_status = 0x%08x\n", priv->netdev->name, desc_status);
 +
-+    // Tell the CoPro to re-read parameters
-+    cmd_queue_result = -1;
-+    while (cmd_queue_result) {
-+        spin_lock(&priv->cmd_que_lock_);
-+        cmd_queue_result = cmd_que_queue_cmd(&priv->cmd_queue_, GMAC_CMD_UPDATE_PARAMS, 0, copro_update_callback);
-+        spin_unlock(&priv->cmd_que_lock_);
-+    }
++      // Update receive statistics from the descriptor status
++      if (is_rx_collision_error(desc_status)) {
++              DBG(20, KERN_INFO "process_rx_packet() %s: Collision (0x%08x:%u bytes)\n", priv->netdev->name, desc_status, desc_len);
++              ++priv->stats.collisions;
++      }
++      if (is_rx_crc_error(desc_status)) {
++              DBG(20, KERN_INFO "process_rx_packet() %s: CRC error (0x%08x:%u bytes)\n", priv->netdev->name, desc_status, desc_len);
++              ++priv->stats.rx_crc_errors;
++              ++priv->stats.rx_errors;
++      }
++      if (is_rx_frame_error(desc_status)) {
++              DBG(20, KERN_INFO "process_rx_packet() %s: frame error (0x%08x:%u bytes)\n", priv->netdev->name, desc_status, desc_len);
++              ++priv->stats.rx_frame_errors;
++              ++priv->stats.rx_errors;
++      }
++      if (is_rx_length_error(desc_status)) {
++              DBG(20, KERN_INFO "process_rx_packet() %s: Length error (0x%08x:%u bytes)\n", priv->netdev->name, desc_status, desc_len);
++              ++priv->stats.rx_length_errors;
++              ++priv->stats.rx_errors;
++      }
++      if (is_rx_csum_error(desc_status)) {
++              DBG(20, KERN_INFO "process_rx_packet() %s: Checksum error (0x%08x:%u bytes)\n", priv->netdev->name, desc_status, desc_len);
++              ++priv->stats.rx_frame_errors;
++              ++priv->stats.rx_errors;
++      }
 +
-+    // Interrupt the CoPro so it sees the new command
-+    writel(1UL << COPRO_SEM_INT_CMD, SYS_CTRL_SEMA_SET_CTRL);
++      return desc_used;
++}
 +
-+    // Wait until the CoPro acknowledges that the update of parameters is complete
-+    down_interruptible(&copro_update_semaphore);
++/*
++ * NAPI receive polling method
++ */
++static int poll(
++      struct napi_struct *napi,
++      int                 budget)
++{
++      gmac_priv_t *priv = container_of(napi, gmac_priv_t, napi_struct);
++      struct net_device *dev = priv->netdev;
++    int rx_work_limit = budget;
++    int work_done = 0;
++    int continue_polling;
++    int finished;
++    int available;
++      int desc_since_refill = 0;
 +
-+    // Tell the CoPro to begin network offload operations
-+    cmd_queue_result = -1;
-+    while (cmd_queue_result) {
-+        spin_lock(&priv->cmd_que_lock_);
-+        cmd_queue_result = cmd_que_queue_cmd(&priv->cmd_queue_, GMAC_CMD_START, 0, copro_start_callback);
-+        spin_unlock(&priv->cmd_que_lock_);
-+    }
++    finished = 0;
++    do {
++        u32 status;
 +
-+    // Interrupt the CoPro so it sees the new command
-+    writel(1UL << COPRO_SEM_INT_CMD, SYS_CTRL_SEMA_SET_CTRL);
++        // While there are receive polling jobs to be done
++        while (rx_work_limit) {
++                      int desc_used;
 +
-+    // Wait until the CoPro acknowledges that it has started
-+    down_interruptible(&copro_start_semaphore);
-+#endif // CONFIG_LEON_COPRO
++                      if (unlikely(priv->rx_buffers_per_page)) {
++                              desc_used = process_rx_packet(priv);
++                      } else {
++                              desc_used = process_rx_packet_skb(priv);
++                      }
 +
-+      // Start NAPI
-+      napi_enable(&priv->napi_struct);
++                      if (!desc_used) {
++                              break;
++                      }
 +
-+    // Start the transmitter and receiver
-+#ifndef CONFIG_LEON_OFFLOAD_TX
-+    dma_reg_set_mask(priv, DMA_OP_MODE_REG, (1UL << DMA_OP_MODE_ST_BIT));
-+#endif // !LEON_OFFLOAD_TX
-+    change_rx_enable(priv, 1, 0, 0);
++            // Increment count of processed packets
++            ++work_done;
++
++            // Decrement our remaining budget
++            if (rx_work_limit > 0) {
++                --rx_work_limit;
++            }
++
++            // Rx overflows seem to upset the GMAC, so try to ensure we never see them
++                      desc_since_refill += desc_used;
++            if (desc_since_refill >= DESC_SINCE_REFILL_LIMIT) {
++                desc_since_refill = 0;
++                refill_rx_ring(dev);
++            }
++        }
 +
-+    // Enable interesting GMAC interrupts
-+    gmac_int_en_set(priv, ((1UL << DMA_INT_ENABLE_NI_BIT)  |
-+                           (1UL << DMA_INT_ENABLE_AI_BIT)  |
-+                           (1UL << DMA_INT_ENABLE_FBE_BIT) |
-+                           (1UL << DMA_INT_ENABLE_RI_BIT)  |
-+                           (1UL << DMA_INT_ENABLE_RU_BIT)  |
-+                           (1UL << DMA_INT_ENABLE_OV_BIT)  |
-+                           (1UL << DMA_INT_ENABLE_RW_BIT)  |
-+                           (1UL << DMA_INT_ENABLE_RS_BIT)  |
-+                           (1UL << DMA_INT_ENABLE_TI_BIT)  |
-+                           (1UL << DMA_INT_ENABLE_UN_BIT)  |
-+                           (1UL << DMA_INT_ENABLE_TJ_BIT)  |
-+                           (1UL << DMA_INT_ENABLE_TS_BIT)));
++        if (rx_work_limit) {
++            // We have unused budget remaining, but apparently no Rx packets to
++            // process
++            available = 0;
 +
-+    // (Re)start the link/PHY state monitoring timer
-+    start_watchdog_timer(priv);
++            // Clear any RI status so we don't immediately get reinterrupted
++            // when we leave polling, due to either a new RI event, or a left
++            // over interrupt from one of the RX descriptors we've already
++            // processed
++            status = dma_reg_read(priv, DMA_STATUS_REG);
++            if (status & (1UL << DMA_STATUS_RI_BIT)) {
++                // Ack the RI, including the normal summary sticky bit
++                dma_reg_write(priv, DMA_STATUS_REG, ((1UL << DMA_STATUS_RI_BIT)  |
++                                                     (1UL << DMA_STATUS_NIS_BIT)));
 +
-+    // Allow the network stack to call hard_start_xmit()
-+    netif_start_queue(dev);
++                // Must check again for available RX descriptors, in case the RI
++                // status came from a new RX descriptor
++                available = rx_available_for_read(&priv->rx_gmac_desc_list_info, 0);
++            }
 +
-+#ifdef DUMP_REGS_ON_GMAC_UP
-+    dump_mac_regs(priv->macBase, priv->dmaBase);
-+#endif // DUMP_REGS_ON_GMAC_UP
++            if (!available) {
++                // We have budget left but no Rx packets to process so stop
++                // polling
++                continue_polling = 0;
++                finished = 1;
++            }
++        } else {
++            // If we have consumed all our budget, don't cancel the
++            // poll, the NAPI instructure assumes we won't
++            continue_polling = 1;
 +
-+    return status;
++            // Must leave poll() routine as no budget left
++            finished = 1;
++        }
++    } while (!finished);
 +
-+gmac_up_err_out:
-+    stop(dev);
++    // Attempt to fill any empty slots in the RX ring
++    refill_rx_ring(dev);
 +
-+    return status;
-+}
++    // Decrement the budget even if we didn't process any packets
++    if (!work_done) {
++        work_done = 1;
++    }
 +
-+static void set_rx_packet_info(struct net_device *dev)
-+{
-+    gmac_priv_t *priv = (gmac_priv_t*)netdev_priv(dev);
-+      int max_packet_buffer_size = dev->mtu + EXTRA_RX_SKB_SPACE;
++    if (!continue_polling) {
++        // No more received packets to process so return to interrupt mode
++        netif_rx_complete(dev, napi);
 +
-+      if (max_packet_buffer_size > max_descriptor_length()) {
-+#ifndef RX_BUFFER_SIZE
-+              priv->rx_buffer_size_ = max_packet_buffer_size;
-+#else // !RX_BUFFER_SIZE
-+              priv->rx_buffer_size_ = RX_BUFFER_SIZE;
-+#endif // ! RX_BUFFER_SIZE
-+              priv->rx_buffers_per_page = GMAC_ALLOC_SIZE / (priv->rx_buffer_size_ + NET_IP_ALIGN);
-+      } else {
-+              priv->rx_buffer_size_ = max_packet_buffer_size;
-+              priv->rx_buffers_per_page = 0;
-+      }
++        // Enable interrupts caused by received packets that may have been
++              // disabled in the ISR before entering polled mode
++        gmac_int_en_set(priv, (1UL << DMA_INT_ENABLE_RI_BIT) |
++                              (1UL << DMA_INT_ENABLE_RU_BIT) |
++                                                         (1UL << DMA_INT_ENABLE_OV_BIT));
++    }
++
++    return work_done;
 +}
 +
-+static int change_mtu(struct net_device *dev, int new_mtu)
++#if defined(CONFIG_LEON_COPRO) && defined(CONFIG_LEON_OFFLOAD_TX)
++static void copro_fill_tx_job(
++    volatile gmac_tx_que_ent_t *job,
++    struct sk_buff             *skb)
 +{
-+    int status = 0;
-+    gmac_priv_t *priv = (gmac_priv_t*)netdev_priv(dev);
-+    int original_mtu = dev->mtu;
++    int i;
++    int nr_frags = skb_shinfo(skb)->nr_frags;
++    unsigned short flags = 0;
++    dma_addr_t hdr_dma_address;
 +
-+    // Check that new MTU is within supported range
-+    if ((new_mtu < MIN_PACKET_SIZE) || (new_mtu > MAX_JUMBO)) {
-+        DBG(1, KERN_WARNING "change_mtu() %s: Invalid MTU %d\n", dev->name, new_mtu);
-+        status = -EINVAL;
-+    } else {
-+        // Put MAC/PHY into quiesent state, causing all current buffers to be
-+        // deallocated and the PHY to powerdown
-+        gmac_down(dev);
++    // if too many fragments call sbk_linearize()
++    // and take the CPU memory copies hit 
++    if (nr_frags > COPRO_NUM_TX_FRAGS_DIRECT) {
++        int err;
++        printk(KERN_WARNING "Fill: linearizing socket buffer as required %d frags and have only %d\n", nr_frags, COPRO_NUM_TX_FRAGS_DIRECT);
++        err = skb_linearize(skb);
++        if (err) {
++            panic("Fill: No free memory");
++        }
 +
-+        // Record the new MTU, so bringing the MAC back up will allocate
-+        // resources to suit the new MTU
-+        dev->mtu = new_mtu;
++        // update nr_frags
++        nr_frags = skb_shinfo(skb)->nr_frags;
++    }
 +
-+              // Set length etc. of rx packets
-+              set_rx_packet_info(dev);
++    // Get a DMA mapping of the packet's data
++    hdr_dma_address = dma_map_single(0, skb->data, skb_headlen(skb), DMA_TO_DEVICE);
++    BUG_ON(dma_mapping_error(hdr_dma_address));
 +
-+        // Reset the PHY to get it into a known state and ensure we have TX/RX
-+        // clocks to allow the GMAC reset to complete
-+        if (phy_reset(priv->netdev)) {
-+            DBG(1, KERN_ERR "change_mtu() %s: Failed to reset PHY\n", dev->name);
-+            status = -EIO;
-+        } else {
-+                      // Set PHY specfic features
-+                      initialise_phy(priv);
++    // Allocate storage for remainder of fragments and create DMA mappings
++    // Get a DMA mapping for as many fragments as will fit into the first level
++    // fragment info. storage within the job structure
++    for (i=0; i < nr_frags; ++i) {
++        struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
++        job->frag_ptr_[i] = dma_map_page(0, frag->page, frag->page_offset, frag->size, DMA_TO_DEVICE);
++        job->frag_len_[i] = frag->size;
++    }
 +
-+            // Record whether jumbo frames should be enabled
-+            priv->jumbo_ = (dev->mtu > NORMAL_PACKET_SIZE);
++    // Is h/w checksumming and possibly TSO required
++    if (likely((skb->ip_summed == CHECKSUM_PARTIAL) &&
++               (ntohs(skb->protocol) == ETH_P_IP))) {
++        flags |= (1UL << TX_JOB_FLAGS_ACCELERATE_BIT);
++    }
 +
-+            // Force or auto-negotiate PHY mode
-+            priv->phy_force_negotiation = 1;
++    // Fill the job description with information about the packet
++    job->skb_         = (u32)skb;
++    job->len_         = skb->len;
++    job->data_len_    = skb->data_len;
++    job->ethhdr_      = hdr_dma_address;
++    job->iphdr_       = hdr_dma_address + (skb_network_header(skb) - skb->data);
++    job->iphdr_csum_  = ((struct iphdr*)skb_network_header(skb))->check;
++    job->tso_segs_    = skb_shinfo(skb)->gso_segs;
++    job->tso_size_    = skb_shinfo(skb)->gso_size;
++    job->flags_       = flags;
++    job->statistics_  = 0;
++}
 +
-+            // Reallocate buffers with new MTU
-+            gmac_up(dev);
-+        }
-+    }
++static void copro_free_tx_resources(volatile gmac_tx_que_ent_t* job)
++{
++    int i;
++    struct sk_buff* skb = (struct sk_buff*)job->skb_;
++    int nr_frags = skb_shinfo(skb)->nr_frags;
 +
-+    // If there was a failure
-+    if (status) {
-+        // Return the MTU to its original value
-+        DBG(1, KERN_INFO "change_mtu() Failed, returning MTU to original value\n");
-+        dev->mtu = original_mtu;
++    // This should never happen, since we check space when we filled
++    // the job in copro_fill_tx_job
++    if (nr_frags > COPRO_NUM_TX_FRAGS_DIRECT) {
++        panic("Free: Insufficient fragment storage, required %d, have only %d", nr_frags, COPRO_NUM_TX_FRAGS_DIRECT);
 +    }
 +
-+    return status;
-+}
++    // Release the DMA mapping for the data directly referenced by the SKB
++    dma_unmap_single(0, job->ethhdr_, skb_headlen(skb), DMA_TO_DEVICE);
 +
-+#ifdef TEST_COPRO
-+DECLARE_MUTEX_LOCKED(start_sem);
-+DECLARE_MUTEX_LOCKED(heartbeat_sem);
++    // Release the DMA mapping for any fragments in the first level fragment
++    // info. storage within the job structure
++    for (i=0; (i < nr_frags) && (i < COPRO_NUM_TX_FRAGS_DIRECT); ++i) {
++        dma_unmap_page(0, job->frag_ptr_[i], job->frag_len_[i], DMA_TO_DEVICE);
++    }
 +
-+void start_callback(volatile gmac_cmd_que_ent_t* entry)
-+{
-+    printk("START callback, operand = 0x%08x\n", entry->operand_);
-+    up(&start_sem);
++    // Inform the network stack that we've finished with the packet
++    dev_kfree_skb_irq(skb);
 +}
 +
-+void heartbeat_callback(volatile gmac_cmd_que_ent_t* entry)
++static void copro_process_pending_tx_skbs(
++    struct net_device          *dev,
++    volatile gmac_tx_que_ent_t *job)
 +{
-+    printk("Heartbeat callback, operand = 0x%08x\n", entry->operand_);
-+    up(&heartbeat_sem);
-+}
++    gmac_priv_t *priv = (gmac_priv_t*)netdev_priv(dev);
 +
-+static void test_copro(gmac_priv_t* priv)
-+{
-+    unsigned long irq_flags;
++    // Process pending SKBs, oldest first
++    do {
++        // Get the oldest pending SKB
++        struct sk_buff *skb;
++        struct list_head *entry = priv->copro_tx_skb_list_.next;
++        BUG_ON(!entry);
++        list_del(entry);
 +
-+    spin_lock(&priv->cmd_que_lock_);
-+    cmd_que_queue_cmd(&priv->cmd_queue_, GMAC_CMD_STOP, 0, 0);
-+    spin_unlock(&priv->cmd_que_lock_);
-+    writel(1UL << COPRO_SEM_INT_CMD, SYS_CTRL_SEMA_SET_CTRL);
-+    mdelay(500);
++        skb = list_entry(entry, struct sk_buff, cb);
++        BUG_ON(!skb);
 +
-+    spin_lock(&priv->cmd_que_lock_);
-+    cmd_que_queue_cmd(&priv->cmd_queue_, GMAC_CMD_START, 0, start_callback);
-+    spin_unlock(&priv->cmd_que_lock_);
-+    writel(1UL << COPRO_SEM_INT_CMD, SYS_CTRL_SEMA_SET_CTRL);
-+    mdelay(500);
++        // Keep track of how many entries are in the pending SKB list
++        --priv->copro_tx_skb_list_count_;
 +
-+    spin_lock(&priv->cmd_que_lock_);
-+    cmd_que_queue_cmd(&priv->cmd_queue_, GMAC_CMD_HEARTBEAT, 0, heartbeat_callback);
-+    spin_unlock(&priv->cmd_que_lock_);
-+    writel(1UL << COPRO_SEM_INT_CMD, SYS_CTRL_SEMA_SET_CTRL);
-+    mdelay(500);
++        // Fill the Tx offload job with the network packet's details
++        copro_fill_tx_job(job, skb);
 +
-+    printk("Waiting for start ack...\n");
-+    down_interruptible(&start_sem);
-+    printk("Start ack received\n");
++        // Enqueue the new Tx offload job with the CoPro
++        tx_que_new_job(dev, job);
 +
-+    printk("Waiting for heartbeat ack...\n");
-+    down_interruptible(&heartbeat_sem);
-+    printk("Heartbeat ack received\n");
++        if (list_empty(&priv->copro_tx_skb_list_)) {
++            // No more pending SKBs
++            break;
++        }
++    } while ((job = tx_que_get_idle_job(dev)));
 +}
-+#endif // TEST_COPRO
 +
-+#ifdef CONFIG_LEON_COPRO 
-+#define SEM_INT_FWD      8
-+#define SEM_INT_ACK      16
-+#define SEM_INT_TX       17
-+#define SEM_INT_STOP_ACK 18
-+
-+#define SEM_INTA_MASK  (1UL << SEM_INT_FWD)
-+#define SEM_INTB_MASK ((1UL << SEM_INT_ACK) | (1UL << SEM_INT_TX) | (1UL << SEM_INT_STOP_ACK))
-+
-+static irqreturn_t copro_sema_intr(int irq, void *dev_id)
++static void finish_xmit(struct net_device *dev)
 +{
-+    struct net_device *dev = (struct net_device *)dev_id;
-+    gmac_priv_t       *priv = (gmac_priv_t*)netdev_priv(dev);
-+    u32                asserted;
-+    u32                fwd_intrs_status = 0;
-+    int                is_fwd_intr;
++    gmac_priv_t                *priv = (gmac_priv_t*)netdev_priv(dev);
++    volatile gmac_tx_que_ent_t *job;
 +
-+    // Read the contents of semaphore A register
-+    asserted = (*((volatile unsigned long*)SYS_CTRL_SEMA_STAT) & SEM_INTA_MASK);
++    // Process all available completed jobs
++    while ((job = tx_que_get_finished_job(dev))) {
++        int aborted;
++        int carrier;
++        int collisions;
++        u32 statistics = job->statistics_;
 +
-+    while (asserted) {
-+        // Extract any forwarded interrupts info
-+        is_fwd_intr = asserted & (1UL << SEM_INT_FWD);
-+        if (is_fwd_intr) {
-+            fwd_intrs_status = ((volatile gmac_fwd_intrs_t*)descriptors_phys_to_virt(priv->copro_params_.fwd_intrs_mailbox_))->status_;
-+        }
++        copro_free_tx_resources(job);
 +
-+        // Clear any interrupts directed at the ARM
-+        *((volatile unsigned long*)SYS_CTRL_SEMA_CLR_CTRL) = asserted;
++        // Accumulate TX statistics returned by CoPro in the job structure
++        priv->stats.tx_bytes   += (statistics & TX_JOB_STATS_BYTES_MASK)   >> TX_JOB_STATS_BYTES_BIT;
++        priv->stats.tx_packets += (statistics & TX_JOB_STATS_PACKETS_MASK) >> TX_JOB_STATS_PACKETS_BIT;
++        aborted    = (statistics & TX_JOB_STATS_ABORT_MASK)     >> TX_JOB_STATS_ABORT_BIT;
++        carrier    = (statistics & TX_JOB_STATS_CARRIER_MASK)   >> TX_JOB_STATS_CARRIER_BIT;
++        collisions = (statistics & TX_JOB_STATS_COLLISION_MASK) >> TX_JOB_STATS_COLLISION_BIT;
++        priv->stats.tx_aborted_errors += aborted;
++        priv->stats.tx_carrier_errors += carrier;
++        priv->stats.collisions        += collisions;
++        priv->stats.tx_errors += (aborted + carrier);
++    }
 +
-+        if (is_fwd_intr) {
-+            // Process any forwarded GMAC interrupts
-+            copro_fwd_intrs_handler(dev_id, fwd_intrs_status);
-+        }
++    // Process any queued pending SKBs for which resources are available
++    if (priv->copro_tx_skb_list_count_ && (job = tx_que_get_idle_job(dev))) {
++        copro_process_pending_tx_skbs(dev, job);
 +
-+        // Stay in interrupt routine if interrupt has been re-asserted
-+        asserted = (*((volatile unsigned long*)SYS_CTRL_SEMA_STAT) & SEM_INTA_MASK);
++        // Record start of transmission, so timeouts will work once they're
++        // implemented
++        dev->trans_start = jiffies;
++
++        // Interrupt the CoPro to cause it to examine the Tx offload queue
++        wmb();
++        writel(1UL << COPRO_SEM_INT_TX, SYS_CTRL_SEMA_SET_CTRL);
 +    }
 +
-+    return IRQ_HANDLED;
++    // If the network stack's Tx queue was stopped and we now have resources
++    // to process more Tx offload jobs
++    if (netif_queue_stopped(dev) &&
++        !tx_que_is_full(&priv->tx_queue_) &&
++        !priv->copro_tx_skb_list_count_) {
++        // Restart the network stack's TX queue
++        netif_wake_queue(dev);
++    }
 +}
-+
-+static irqreturn_t copro_semb_intr(int irq, void *dev_id)
++#else
++static void finish_xmit(struct net_device *dev)
 +{
-+    struct net_device *dev = (struct net_device *)dev_id;
-+    gmac_priv_t       *priv = (gmac_priv_t*)netdev_priv(dev);
-+    u32                asserted;
++    gmac_priv_t *priv = (gmac_priv_t*)netdev_priv(dev);
++    unsigned     descriptors_freed = 0;
++    u32          desc_status = 0;
 +
-+    // Read the contents of semaphore B register
-+    asserted = (*((volatile unsigned long*)SYS_CTRL_SEMA_STAT) & SEM_INTB_MASK);
++    // Handle transmit descriptors for the completed packet transmission
++    while (1) {
++        struct sk_buff *skb;
++        tx_frag_info_t  fragment;
++        int             buffer_owned;
++              int                              desc_index;
 +
-+    while (asserted) {
-+        // Clear any interrupts directed at the ARM
-+        *((volatile unsigned long*)SYS_CTRL_SEMA_CLR_CTRL) = asserted;
++        // Get tx descriptor content, accumulating status for all buffers
++        // contributing to each packet
++              desc_index = get_tx_descriptor(priv, &skb, &desc_status, &fragment, &buffer_owned);
 +
-+        // Process any outstanding command acknowledgements
-+        if (asserted & (1UL << SEM_INT_ACK)) {
-+            while (!cmd_que_dequeue_ack(&priv->cmd_queue_));
-+        }
++              if (desc_index < 0) {
++                      // No more completed Tx packets
++                      break;
++              }
 +
-+        // Process STOP completion signal
-+        if (asserted & (1UL << SEM_INT_STOP_ACK)) {
-+            up(&priv->copro_stop_complete_semaphore_);
++        // Only unmap DMA buffer if descriptor owned the buffer
++        if (buffer_owned) {
++            // Release the DMA mapping for the buffer
++            dma_unmap_single(0, fragment.phys_adr, fragment.length, DMA_TO_DEVICE);
 +        }
 +
-+#ifdef CONFIG_LEON_OFFLOAD_TX
-+        // Process any completed TX offload jobs
-+        if (asserted & (1UL << SEM_INT_TX)) {
-+            finish_xmit(dev);
-+        }
-+#endif // CONFIG_LEON_OFFLOAD_TX
++        // When all buffers contributing to a packet have been processed
++        if (skb) {
++            // Check the status of the transmission
++            if (likely(is_tx_valid(desc_status))) {
++                priv->stats.tx_bytes += skb->len;
++                priv->stats.tx_packets++;
++            } else {
++                priv->stats.tx_errors++;
++                if (is_tx_aborted(desc_status)) {
++                    ++priv->stats.tx_aborted_errors;
++                }
++                if (is_tx_carrier_error(desc_status)) {
++                    ++priv->stats.tx_carrier_errors;
++                }
++            }
 +
-+        // Stay in interrupt routine if interrupt has been re-asserted
-+        asserted = (*((volatile unsigned long*)SYS_CTRL_SEMA_STAT) & SEM_INTB_MASK);
-+    }
++            if (unlikely(is_tx_collision_error(desc_status))) {
++                ++priv->stats.collisions;
++            }
 +
-+    return IRQ_HANDLED;
-+}
-+#endif // CONFIG_LEON_COPRO 
++            // Inform the network stack that packet transmission has finished
++            dev_kfree_skb_irq(skb);
 +
-+static int open(struct net_device *dev)
-+{
-+    gmac_priv_t* priv = (gmac_priv_t*)netdev_priv(dev);
-+    int status;
++            // Start accumulating status for the next packet
++            desc_status = 0;
++        }
 +
-+    // Ensure the MAC block is properly reset
-+    writel(1UL << SYS_CTRL_RSTEN_MAC_BIT, SYS_CTRL_RSTEN_SET_CTRL);
-+    writel(1UL << SYS_CTRL_RSTEN_MAC_BIT, SYS_CTRL_RSTEN_CLR_CTRL);
++        // Track how many descriptors we make available, so we know
++        // if we need to re-start of network stack's TX queue processing
++        ++descriptors_freed;
++    }
 +
-+    // Enable the clock to the MAC block
-+    writel(1UL << SYS_CTRL_CKEN_MAC_BIT, SYS_CTRL_CKEN_SET_CTRL);
++    // If the TX queue is stopped, there may be a pending TX packet waiting to
++    // be transmitted
++    if (unlikely(netif_queue_stopped(dev))) {
++              // No locking with hard_start_xmit() required, as queue is already
++              // stopped so hard_start_xmit() won't touch the h/w
 +
-+    // Ensure reset and clock operations are complete
-+    wmb();
++        // If any TX descriptors have been freed and there is an outstanding TX
++        // packet waiting to be queued due to there not having been a TX
++        // descriptor available when hard_start_xmit() was presented with an skb
++        // by the network stack
++        if (priv->tx_pending_skb) {
++            // Construct the GMAC specific DMA descriptor
++            if (set_tx_descriptor(priv,
++                                  priv->tx_pending_skb,
++                                  priv->tx_pending_fragments,
++                                  priv->tx_pending_fragment_count,
++                                  priv->tx_pending_skb->ip_summed == CHECKSUM_PARTIAL) >= 0) {
++                // No TX packets now outstanding
++                priv->tx_pending_skb = 0;
++                priv->tx_pending_fragment_count = 0;
 +
-+    // Reset the PHY to get it into a known state and ensure we have TX/RX clocks
-+    // to allow the GMAC reset to complete
-+    if (phy_reset(priv->netdev)) {
-+        DBG(1, KERN_ERR "open() %s: Failed to reset PHY\n", dev->name);
-+        status = -EIO;
-+        goto open_err_out;
-+    }
++                // We have used one of the TX descriptors freed by transmission
++                // completion processing having occured above
++                --descriptors_freed;
 +
-+      // Set PHY specfic features
-+      initialise_phy(priv);
++                // Issue a TX poll demand to restart TX descriptor processing, as we
++                // have just added one, in case it had found there were no more
++                // pending transmission
++                dma_reg_write(priv, DMA_TX_POLL_REG, 0);
++            }
++        }
 +
-+    // Check that the MAC address is valid.  If it's not, refuse to bring the
-+    // device up
-+    if (!is_valid_ether_addr(dev->dev_addr)) {
-+        DBG(1, KERN_ERR "open() %s: MAC address invalid\n", dev->name);
-+        status = -EINVAL;
-+        goto open_err_out;
++        // If there are TX descriptors available we should restart the TX queue
++        if (descriptors_freed) {
++            // The TX queue had been stopped by hard_start_xmit() due to lack of
++            // TX descriptors, so restart it now that we've freed at least one
++            netif_wake_queue(dev);
++        }
 +    }
++}
++#endif // CONFIG_LEON_COPRO && CONFIG_LEON_OFFLOAD_TX
 +
-+#ifdef CONFIG_LEON_COPRO 
-+    // Register ISRs for the semaphore register interrupt sources, which will
-+    // originate from the CoPro
-+    if (request_irq(priv->copro_a_irq_, &copro_sema_intr, 0, "SEMA", dev)) {
-+        panic("open: Failed to allocate semaphore A %u\n", priv->copro_a_irq_);
-+        status = -ENODEV;
-+        goto open_err_out;
-+    }
-+    priv->copro_a_irq_alloced_ = 1;
++#ifndef CONFIG_LEON_COPRO
++static void process_non_dma_ints(u32 raw_status)
++{
++    printk(KERN_ERR "Found GPI/GMI/GLI interrupt\n");
++}
++#endif // !CONFIG_LEON_COPRO
 +
-+    if (request_irq(priv->copro_b_irq_, &copro_semb_intr, 0, "SEMB", dev)) {
-+        panic("open: Failed to allocate semaphore B %u\n", priv->copro_b_irq_);
-+        status = -ENODEV;
-+        goto open_err_out;
-+    }
-+    priv->copro_b_irq_alloced_ = 1;
-+#else // CONFIG_LEON_COPRO 
-+    // Allocate the IRQ
-+    if (request_irq(dev->irq, &int_handler, 0, dev->name, dev)) {
-+        DBG(1, KERN_ERR "open() %s: Failed to allocate irq %d\n", dev->name, dev->irq);
-+        status = -ENODEV;
-+        goto open_err_out;
++#ifdef CONFIG_LEON_COPRO
++static void copro_fwd_intrs_handler(
++    void *dev_id,
++    u32   status)
++{
++    struct net_device *dev = (struct net_device *)dev_id;
++    gmac_priv_t       *priv = (gmac_priv_t*)netdev_priv(dev);
++    int                restart_watchdog = 0;
++    int                restart_tx = 0;
++    int                poll_tx = 0;
++
++    // Test for normal receive interrupt
++    if (status & (1UL << DMA_STATUS_RI_BIT)) {
++        if (netif_rx_schedule_prep(dev, &priv->napi_struct)) {
++            // Tell system we have work to be done
++            __netif_rx_schedule(dev, &priv->napi_struct);
++        } else {
++            printk(KERN_ERR "copro_fwd_intrs_handler() %s: RX interrupt while in poll\n", dev->name);
++        }
 +    }
-+    priv->have_irq = 1;
-+#endif // CONFIG_LEON_COPRO 
-+
-+    // Need a consistent DMA mapping covering all the memory occupied by DMA
-+    // unified descriptor array, as both CPU and DMA engine will be reading and
-+    // writing descriptor fields.
-+    priv->desc_vaddr    = (gmac_dma_desc_t*)GMAC_DESC_ALLOC_START;
-+    priv->desc_dma_addr = GMAC_DESC_ALLOC_START_PA;
 +
-+    if (!priv->desc_vaddr) {
-+        DBG(1, KERN_ERR "open() %s: Failed to allocate consistent memory for DMA descriptors\n", dev->name);
-+        status = -ENOMEM;
-+        goto open_err_out;
++    // Test for unavailable RX buffers - CoPro should have disabled
++    if (unlikely(status & (1UL << DMA_STATUS_RU_BIT))) {
++        DBG(30, KERN_INFO "int_handler() %s: RX buffer unavailable\n", dev->name);
++        // Accumulate receive statistics
++        ++priv->stats.rx_over_errors;
++        ++priv->stats.rx_errors;
 +    }
 +
-+      // Allocate memory to hold shadow of GMAC descriptors
-+      if (!(priv->tx_desc_shadow_ = kmalloc(NUM_TX_DMA_DESCRIPTORS * sizeof(gmac_dma_desc_t), GFP_KERNEL))) {
-+        DBG(1, KERN_ERR "open() %s: Failed to allocate memory for Tx descriptor shadows\n", dev->name);
-+        status = -ENOMEM;
-+        goto open_err_out;
-+      }
-+      if (!(priv->rx_desc_shadow_ = kmalloc(NUM_RX_DMA_DESCRIPTORS * sizeof(gmac_dma_desc_t), GFP_KERNEL))) {
-+        DBG(1, KERN_ERR "open() %s: Failed to allocate memory for Rx descriptor shadows\n", dev->name);
-+        status = -ENOMEM;
-+        goto open_err_out;
++    // Test for Rx overflow - CoPro should have disabled
++      if (unlikely(status & (1UL << DMA_STATUS_OVF_BIT))) {
++              DBG(30, KERN_INFO "int_handler() %s: Rx overflow\n", dev->name);
++              // Accumulate receive statistics
++              ++priv->stats.rx_fifo_errors;
++              ++priv->stats.rx_errors;
 +      }
 +
-+      // Record whether jumbo frames should be enabled
-+    priv->jumbo_ = (dev->mtu > NORMAL_PACKET_SIZE);
-+
-+      set_rx_packet_info(dev);
-+
-+#ifdef CONFIG_LEON_COPRO 
-+    // Allocate SRAM for the command queue entries
-+    priv->copro_params_.cmd_que_head_ = DESCRIPTORS_BASE_PA + DESCRIPTORS_SIZE;
++    // Test for normal TX interrupt
++    if (status & ((1UL << DMA_STATUS_TI_BIT) |
++                  (1UL << DMA_STATUS_ETI_BIT))) {
++#ifndef CONFIG_LEON_OFFLOAD_TX
++        // Finish packet transmision started by start_xmit
++        finish_xmit(dev);
++#endif // !CONFIG_LEON_OFFLOAD_TX
++    }
 +
-+    priv->copro_params_.cmd_que_tail_ =
-+        (u32)((gmac_cmd_que_ent_t*)(priv->copro_params_.cmd_que_head_) + priv->copro_cmd_que_num_entries_);
-+    priv->copro_params_.fwd_intrs_mailbox_ = priv->copro_params_.cmd_que_tail_;
-+    priv->copro_params_.tx_que_head_ = priv->copro_params_.fwd_intrs_mailbox_ + sizeof(gmac_fwd_intrs_t);
-+    priv->copro_params_.tx_que_tail_ =
-+        (u32)((gmac_tx_que_ent_t*)(priv->copro_params_.tx_que_head_) + priv->copro_tx_que_num_entries_);
-+    priv->copro_params_.free_start_ = priv->copro_params_.tx_que_tail_;
++    // Test for abnormal transmitter interrupt where there may be completed
++    // packets waiting to be processed
++    if (unlikely(status & ((1UL << DMA_STATUS_TJT_BIT) |
++                           (1UL << DMA_STATUS_UNF_BIT)))) {
++#ifndef CONFIG_LEON_OFFLOAD_TX
++        // Complete processing of any TX packets closed by the DMA
++        finish_xmit(dev);
++#endif // !CONFIG_LEON_OFFLOAD_TX
 +
-+    // Set RX interrupt mitigation behaviour
-+    priv->copro_params_.rx_mitigation_        = COPRO_RX_MITIGATION;
-+    priv->copro_params_.rx_mitigation_frames_ = COPRO_RX_MITIGATION_FRAMES;
-+    priv->copro_params_.rx_mitigation_usec_   = COPRO_RX_MITIGATION_USECS;
++        if (status & (1UL << DMA_STATUS_TJT_BIT)) {
++            // A transmit jabber timeout causes the transmitter to enter the
++            // stopped state
++            DBG(50, KERN_INFO "int_handler() %s: TX jabber timeout\n", dev->name);
++            restart_tx = 1;
++        } else {
++            DBG(51, KERN_INFO "int_handler() %s: TX underflow\n", dev->name);
++        }
 +
-+    // Initialise command queue metadata
-+    cmd_que_init(
-+        &priv->cmd_queue_,
-+        (gmac_cmd_que_ent_t*)descriptors_phys_to_virt(priv->copro_params_.cmd_que_head_),
-+        priv->copro_cmd_que_num_entries_);
++        // Issue a TX poll demand in an attempt to restart TX descriptor
++        // processing
++        poll_tx = 1;
++    }
 +
-+    // Initialise tx offload queue metadata
-+    tx_que_init(
-+        &priv->tx_queue_,
-+        (gmac_tx_que_ent_t*)descriptors_phys_to_virt(priv->copro_params_.tx_que_head_),
-+        priv->copro_tx_que_num_entries_);
++    // Test for any of the error states which we deal with directly within
++    // this interrupt service routine.
++    if (unlikely(status & ((1UL << DMA_STATUS_ERI_BIT) |
++                           (1UL << DMA_STATUS_RWT_BIT) |
++                           (1UL << DMA_STATUS_RPS_BIT) |
++                           (1UL << DMA_STATUS_TPS_BIT) |
++                           (1UL << DMA_STATUS_FBE_BIT)))) {
++        // Test for early RX interrupt
++        if (status & (1UL << DMA_STATUS_ERI_BIT)) {
++            // Don't expect to see this, as never enable it
++            DBG(30, KERN_WARNING "int_handler() %s: Early RX \n", dev->name);
++        }
 +
-+    // Allocate DMA coherent space for the parameter block shared with the CoPro
-+    priv->shared_copro_params_ = dma_alloc_coherent(0, sizeof(copro_params_t), &priv->shared_copro_params_pa_, GFP_KERNEL);
-+    if (!priv->shared_copro_params_) {
-+        DBG(1, KERN_ERR "open() %s: Failed to allocate DMA coherent space for parameters\n");
-+        status = -ENOMEM;
-+        goto open_err_out;
-+    }
++        if (status & (1UL << DMA_STATUS_RWT_BIT)) {
++            DBG(30, KERN_INFO "int_handler() %s: RX watchdog timeout\n", dev->name);
++            // Accumulate receive statistics
++            ++priv->stats.rx_frame_errors;
++            ++priv->stats.rx_errors;
++            restart_watchdog = 1;
++        }
 +
-+    // Update the CoPro's parameters with the current MTU
-+    priv->copro_params_.mtu_ = dev->mtu;
++        if (status & (1UL << DMA_STATUS_RPS_BIT)) {
++            // Mask to extract the receive status field from the status register
++//            u32 rs_mask = ((1UL << DMA_STATUS_RS_NUM_BITS) - 1) << DMA_STATUS_RS_BIT;
++//            u32 rs = (status & rs_mask) >> DMA_STATUS_RS_BIT;
++//            printk("int_handler() %s: RX process stopped 0x%x\n", dev->name, rs);
++            ++priv->stats.rx_errors;
++            restart_watchdog = 1;
 +
-+    // Fill the shared CoPro parameter block from the ARM's local copy
-+    memcpy(priv->shared_copro_params_, &priv->copro_params_, sizeof(copro_params_t));
++            // Restart the receiver
++            DBG(35, KERN_INFO "int_handler() %s: Restarting receiver\n", dev->name);
++            change_rx_enable(priv, 1, 0, 1);
++        }
 +
-+    // Load CoPro program and start it running
-+    init_copro(leon_srec, priv->shared_copro_params_pa_);
++        if (status & (1UL << DMA_STATUS_TPS_BIT)) {
++            // Mask to extract the transmit status field from the status register
++//            u32 ts_mask = ((1UL << DMA_STATUS_TS_NUM_BITS) - 1) << DMA_STATUS_TS_BIT;
++//            u32 ts = (status & ts_mask) >> DMA_STATUS_TS_BIT;
++//            printk("int_handler() %s: TX process stopped 0x%x\n", dev->name, ts);
++            ++priv->stats.tx_errors;
++            restart_watchdog = 1;
++            restart_tx = 1;
++        }
 +
-+    // Enable selected semaphore register bits to cause ARM interrupts
-+    *((volatile unsigned long*)SYS_CTRL_SEMA_MASKA_CTRL) = SEM_INTA_MASK;
-+    *((volatile unsigned long*)SYS_CTRL_SEMA_MASKB_CTRL) = SEM_INTB_MASK;
++        // Test for pure error interrupts
++        if (status & (1UL << DMA_STATUS_FBE_BIT)) {
++            // Mask to extract the bus error status field from the status register
++//            u32 eb_mask = ((1UL << DMA_STATUS_EB_NUM_BITS) - 1) << DMA_STATUS_EB_BIT;
++//            u32 eb = (status & eb_mask) >> DMA_STATUS_EB_BIT;
++//            printk("int_handler() %s: Bus error 0x%x\n", dev->name, eb);
++            restart_watchdog = 1;
++        }
 +
-+#ifdef TEST_COPRO
-+    // Send test commands to the CoPro
-+    test_copro(priv);
-+#endif // TEST_COPRO
-+#endif // CONFIG_LEON_COPRO 
++        if (restart_watchdog) {
++            // Restart the link/PHY state watchdog immediately, which will
++            // attempt to restart the system
++            mod_timer(&priv->watchdog_timer, jiffies);
++            restart_watchdog = 0;
++        }
++    }
 +
-+    // Do startup operations that are in common with gmac_down()/_up() processing
-+    priv->mii_init_media = 1;
-+    priv->phy_force_negotiation = 1;
-+    status = gmac_up(dev);
-+    if (status) {
-+        goto open_err_out;
++    if (unlikely(restart_tx)) {
++        // Restart the transmitter, causes am implicit Tx descriptor list poll
++        DBG(35, KERN_INFO "int_handler() %s: Restarting transmitter\n", dev->name);
++#ifndef CONFIG_LEON_OFFLOAD_TX
++        dma_reg_set_mask(priv, DMA_OP_MODE_REG, (1UL << DMA_OP_MODE_ST_BIT));
++#endif // !CONFIG_LEON_OFFLOAD_TX
++        poll_tx = 0;
 +    }
 +
-+    return 0;
++    if (unlikely(poll_tx)) {
++        // Issue a TX poll demand in an attempt to restart TX descriptor
++        // processing
++        DBG(33, KERN_INFO "int_handler() %s: Issuing Tx poll demand\n", dev->name);
++#ifndef CONFIG_LEON_OFFLOAD_TX
++        dma_reg_write(priv, DMA_TX_POLL_REG, 0);
++#endif // !CONFIG_LEON_OFFLOAD_TX
++    }
++}
++#else // CONFIG_LEON_COPRO 
++static irqreturn_t int_handler(int int_num, void* dev_id)
++{
++    struct net_device *dev = (struct net_device *)dev_id;
++    gmac_priv_t* priv = (gmac_priv_t*)netdev_priv(dev);
++    u32 int_enable;
++    int rx_polling;
++    u32 raw_status;
++    u32 status;
 +
-+open_err_out:
-+    stop(dev);
++    /** Read the interrupt enable register to determine if we're in rx poll mode
++     *  Id like to get rid of this read, if a more efficient way of determining
++     *  whether we are polling is available */
++    spin_lock(&priv->cmd_que_lock_);
++    int_enable = dma_reg_read(priv, DMA_INT_ENABLE_REG);
++    spin_unlock(&priv->cmd_que_lock_);
 +
-+    return status;
-+}
++    rx_polling = !(int_enable & (1UL << DMA_INT_ENABLE_RI_BIT));
 +
-+#if defined(CONFIG_LEON_COPRO) && defined(CONFIG_LEON_OFFLOAD_TX)
-+static int hard_start_xmit(
-+    struct sk_buff *skb,
-+    struct net_device *dev)
-+{
-+    gmac_priv_t                *priv = (gmac_priv_t*)netdev_priv(dev);
-+    volatile gmac_tx_que_ent_t *job;
-+    unsigned long               irq_flags;
++    // Get interrupt status
++    raw_status = dma_reg_read(priv, DMA_STATUS_REG);
 +
-+    if (skb_shinfo(skb)->frag_list) {
-+        panic("Frag list - can't handle this!\n");
++    // MMC, PMT and GLI interrupts are not masked by the interrupt enable
++    // register, so must deal with them on the raw status
++    if (unlikely(raw_status & ((1UL << DMA_STATUS_GPI_BIT) |
++                      (1UL << DMA_STATUS_GMI_BIT) |
++                      (1UL << DMA_STATUS_GLI_BIT)))) {
++        process_non_dma_ints(raw_status);
 +    }
 +
-+    // Protection against concurrent operations in ISR and hard_start_xmit()
-+    if (!spin_trylock_irqsave(&priv->tx_spinlock_, irq_flags)) {
-+        return NETDEV_TX_LOCKED;
-+    }
++    // Get status of enabled interrupt sources
++    status = raw_status & int_enable;
 +
-+    // NETIF_F_LLTX apparently introduces a potential for hard_start_xmit() to
-+    // be called when the queue has been stopped (although I think only in SMP)
-+    // so do a check here to make sure we should proceed
-+    if (netif_queue_stopped(dev)) {
-+        spin_unlock_irqrestore(&priv->tx_spinlock_, irq_flags);
-+        return NETDEV_TX_BUSY;
-+    }
++    while (status) {
++        // Whether the link/PHY watchdog timer should be restarted
++        int restart_watchdog = 0;
++        int restart_tx       = 0;
++        int poll_tx          = 0;
++        u32 int_disable_mask = 0;
 +
-+    job = tx_que_get_idle_job(dev);
-+    if (!job) {
-+        // Tx offload queue is full, so add skb to pending skb list
-+        list_add_tail((struct list_head*)&skb->cb, &priv->copro_tx_skb_list_);
++        // Test for RX interrupt resulting from sucessful reception of a packet-
++        // must do this before ack'ing, else otherwise can get into trouble with
++        // the sticky summary bits when we try to disable further RI interrupts
++        if (status & (1UL << DMA_STATUS_RI_BIT)) {
++//printk("RI ");
++            // Disable interrupts caused by received packets as henceforth
++            // we shall poll for packet reception
++            int_disable_mask |= (1UL << DMA_INT_ENABLE_RI_BIT);
 +
-+        // Keep track of how many entries are in the pending SKB list
-+        ++priv->copro_tx_skb_list_count_;
++            // Do NAPI compatible receive processing for RI interrupts
++            if (likely(netif_rx_schedule_prep(dev, &priv->napi_struct))) {
++                // Remember that we are polling, so we ignore RX events for the
++                // remainder of the ISR
++                rx_polling = 1;
 +
-+        // Have we queued the max allowed number of SKBs?
-+        if (priv->copro_tx_skb_list_count_ >= COPRO_MAX_QUEUED_TX_SKBS) {
-+            // Stop further calls to hard_start_xmit() until some descriptors
-+            // are freed up by already queued TX packets being completed
-+            netif_stop_queue(dev);
++                // Tell system we have work to be done
++                __netif_rx_schedule(dev, &priv->napi_struct);
++            } else {
++                printk(KERN_ERR "int_handler() %s: RX interrupt while in poll\n", dev->name);
++            }
 +        }
-+    } else {
-+        if (priv->copro_tx_skb_list_count_) {
-+            // Have queued pending SKBs, so add new SKB to tail of pending list
-+            list_add_tail((struct list_head*)&skb->cb, &priv->copro_tx_skb_list_);
 +
-+            // Keep track of how many entries are in the pending SKB list
-+            ++priv->copro_tx_skb_list_count_;
-+
-+            // Process pending SKBs, oldest first
-+            copro_process_pending_tx_skbs(dev, job);
-+        } else {
-+            // Fill the Tx offload job with the network packet's details
-+            copro_fill_tx_job(job, skb);
++        // Test for unavailable RX buffers - must do this before ack'ing, else
++        // otherwise can get into trouble with the sticky summary bits
++        if (unlikely(status & (1UL << DMA_STATUS_RU_BIT))) {
++            printk(/*DBG(30, KERN_INFO */"int_handler() %s: RX buffer unavailable\n", dev->name);
++            // Accumulate receive statistics
++            ++priv->stats.rx_over_errors;
++            ++priv->stats.rx_errors;
 +
-+            // Enqueue the new Tx offload job with the CoPro
-+            tx_que_new_job(dev, job);
++            // Disable RX buffer unavailable reporting, so we don't get swamped
++            int_disable_mask |= (1UL << DMA_INT_ENABLE_RU_BIT);
 +        }
 +
-+        // Record start of transmission, so timeouts will work once they're
-+        // implemented
-+        dev->trans_start = jiffies;
++              if (unlikely(status & (1UL << DMA_STATUS_OVF_BIT))) {
++                      printk(/*DBG(30, KERN_INFO */"int_handler() %s: RX overflow\n", dev->name);
++                      // Accumulate receive statistics
++                      ++priv->stats.rx_fifo_errors;
++                      ++priv->stats.rx_errors;
 +
-+        // Interrupt the CoPro to cause it to examine the Tx offload queue
-+        wmb();
-+        writel(1UL << COPRO_SEM_INT_TX, SYS_CTRL_SEMA_SET_CTRL);
++            // Disable RX overflow reporting, so we don't get swamped
++            int_disable_mask |= (1UL << DMA_INT_ENABLE_OV_BIT);
++              }
 +
-+        // If the network stack's Tx queue was stopped and we now have resources
-+        // to process more Tx offload jobs
-+        if (netif_queue_stopped(dev) &&
-+            !tx_que_is_full(&priv->tx_queue_) &&
-+            !priv->copro_tx_skb_list_count_) {
-+            // Restart the network stack's TX queue
-+            netif_wake_queue(dev);
++        // Do any interrupt disabling with a single register write
++        if (int_disable_mask) {
++            gmac_int_en_clr(priv, int_disable_mask, 0);
++
++            // Update our record of the current interrupt enable status
++            int_enable &= ~int_disable_mask;
 +        }
-+    }
 +
-+    spin_unlock_irqrestore(&priv->tx_spinlock_, irq_flags);
++        // The broken GMAC interrupt mechanism with its sticky summary bits
++        // means that we have to ack all asserted interrupts here; we can't not
++        // ack the RI interrupt source as we might like to (in order that the
++        // poll() routine could examine the status) because if it was asserted
++        // prior to being masked above, then the summary bit(s) would remain
++        // asserted and cause an immediate re-interrupt.
++        dma_reg_write(priv, DMA_STATUS_REG, status | ((1UL << DMA_STATUS_NIS_BIT) |
++                                                      (1UL << DMA_STATUS_AIS_BIT)));
 +
-+    return NETDEV_TX_OK;
-+}
-+#else
-+static inline void unmap_fragments(
-+    tx_frag_info_t *frags,
-+    int             count)
-+{
-+    while (count--) {
-+        dma_unmap_single(0, frags->phys_adr, frags->length, DMA_TO_DEVICE);
-+        ++frags;
-+    }
-+}
++        // Test for normal TX interrupt
++        if (status & ((1UL << DMA_STATUS_TI_BIT) |
++                      (1UL << DMA_STATUS_ETI_BIT))) {
++            // Finish packet transmision started by start_xmit
++            finish_xmit(dev);
++        }
 +
-+static int hard_start_xmit(
-+    struct sk_buff    *skb,
-+    struct net_device *dev)
-+{
-+    gmac_priv_t            *priv = (gmac_priv_t*)netdev_priv(dev);
-+    unsigned long           irq_flags;
-+    struct skb_shared_info *shinfo = skb_shinfo(skb);
-+    int                     fragment_count = shinfo->nr_frags + 1;
-+    tx_frag_info_t          fragments[fragment_count];
-+    int                     frag_index;
++        // Test for abnormal transmitter interrupt where there may be completed
++        // packets waiting to be processed
++        if (unlikely(status & ((1UL << DMA_STATUS_TJT_BIT) |
++                               (1UL << DMA_STATUS_UNF_BIT)))) {
++            // Complete processing of any TX packets closed by the DMA
++            finish_xmit(dev);
 +
-+    // Get consistent DMA mappings for the SDRAM to be DMAed from by the GMAC,
-+    // causing a flush from the CPU's cache to the memory.
++            if (status & (1UL << DMA_STATUS_TJT_BIT)) {
++                // A transmit jabber timeout causes the transmitter to enter the
++                // stopped state
++                DBG(50, KERN_INFO "int_handler() %s: TX jabber timeout\n", dev->name);
++                restart_tx = 1;
++            } else {
++                DBG(51, KERN_INFO "int_handler() %s: TX underflow\n", dev->name);
++            }
 +
-+    // Do the DMA mappings before acquiring the tx lock, even though it complicates
-+    // the later code, as this can be a long operation involving cache flushing
++            // Issue a TX poll demand in an attempt to restart TX descriptor
++            // processing
++            poll_tx = 1;
++        }
 +
-+    // Map the main buffer
-+    fragments[0].length = skb_headlen(skb);
-+    fragments[0].phys_adr = dma_map_single(0, skb->data, skb_headlen(skb), DMA_TO_DEVICE);
-+    BUG_ON(dma_mapping_error(fragments[0].phys_adr));
++        // Test for any of the error states which we deal with directly within
++        // this interrupt service routine.
++        if (unlikely(status & ((1UL << DMA_STATUS_ERI_BIT) |
++                               (1UL << DMA_STATUS_RWT_BIT) |
++                               (1UL << DMA_STATUS_RPS_BIT) |
++                               (1UL << DMA_STATUS_TPS_BIT) |
++                               (1UL << DMA_STATUS_FBE_BIT)))) {
++            // Test for early RX interrupt
++            if (status & (1UL << DMA_STATUS_ERI_BIT)) {
++                // Don't expect to see this, as never enable it
++                DBG(30, KERN_WARNING "int_handler() %s: Early RX \n", dev->name);
++            }
 +
-+    // Map any SG fragments
-+    for (frag_index = 0; frag_index < shinfo->nr_frags; ++frag_index) {
-+        skb_frag_t *frag = &shinfo->frags[frag_index];
++            if (status & (1UL << DMA_STATUS_RWT_BIT)) {
++                DBG(30, KERN_INFO "int_handler() %s: RX watchdog timeout\n", dev->name);
++                // Accumulate receive statistics
++                ++priv->stats.rx_frame_errors;
++                ++priv->stats.rx_errors;
++                restart_watchdog = 1;
++            }
 +
-+        fragments[frag_index + 1].length = frag->size;
-+        fragments[frag_index + 1].phys_adr = dma_map_page(0, frag->page, frag->page_offset, frag->size, DMA_TO_DEVICE);
-+        BUG_ON(dma_mapping_error(fragments[frag_index + 1].phys_adr));
-+    }
++            if (status & (1UL << DMA_STATUS_RPS_BIT)) {
++                              // Mask to extract the receive status field from the status register
++                              u32 rs_mask = ((1UL << DMA_STATUS_RS_NUM_BITS) - 1) << DMA_STATUS_RS_BIT;
++                              u32 rs = (status & rs_mask) >> DMA_STATUS_RS_BIT;
++                              printk(/*DBG(30, KERN_INFO */"int_handler() %s: RX process stopped 0x%x\n", dev->name, rs);
++                              ++priv->stats.rx_errors;
++                              restart_watchdog = 1;
 +
-+    // Protection against concurrent operations in ISR and hard_start_xmit()
-+    if (unlikely(!spin_trylock_irqsave(&priv->tx_spinlock_, irq_flags))) {
-+        unmap_fragments(fragments, fragment_count);
-+        return NETDEV_TX_LOCKED;
-+    }
++                // Restart the receiver
++                printk(/*DBG(35, KERN_INFO */"int_handler() %s: Restarting receiver\n", dev->name);
++                dma_reg_set_mask(priv, DMA_OP_MODE_REG, (1UL << DMA_OP_MODE_SR_BIT));
++            }
 +
-+    // NETIF_F_LLTX apparently introduces a potential for hard_start_xmit() to
-+    // be called when the queue has been stopped (although I think only in SMP)
-+    // so do a check here to make sure we should proceed
-+    if (unlikely(netif_queue_stopped(dev))) {
-+        unmap_fragments(fragments, fragment_count);
-+        spin_unlock_irqrestore(&priv->tx_spinlock_, irq_flags);
-+        return NETDEV_TX_BUSY;
-+    }
++            if (status & (1UL << DMA_STATUS_TPS_BIT)) {
++                              // Mask to extract the transmit status field from the status register
++//                            u32 ts_mask = ((1UL << DMA_STATUS_TS_NUM_BITS) - 1) << DMA_STATUS_TS_BIT;
++//                            u32 ts = (status & ts_mask) >> DMA_STATUS_TS_BIT;
++//                            DBG(30, KERN_INFO "int_handler() %s: TX process stopped 0x%x\n", dev->name, ts);
++                ++priv->stats.tx_errors;
++                restart_watchdog = 1;
++                restart_tx = 1;
++            }
 +
-+    // Construct the GMAC DMA descriptor
-+    if (unlikely(set_tx_descriptor(priv,
-+                          skb,
-+                          fragments,
-+                          fragment_count,
-+                          skb->ip_summed == CHECKSUM_PARTIAL) < 0)) {
-+        // Shouldn't see a full ring without the queue having already been
-+        // stopped, and the queue should already have been stopped if we have
-+        // already queued a single pending packet
-+        if (priv->tx_pending_skb) {
-+            printk(KERN_WARNING "hard_start_xmit() Ring full and pending packet already queued\n");
-+            unmap_fragments(fragments, fragment_count);
-+            spin_unlock_irqrestore(&priv->tx_spinlock_, irq_flags);
-+            return NETDEV_TX_BUSY;
++            // Test for pure error interrupts
++            if (status & (1UL << DMA_STATUS_FBE_BIT)) {
++                              // Mask to extract the bus error status field from the status register
++//                            u32 eb_mask = ((1UL << DMA_STATUS_EB_NUM_BITS) - 1) << DMA_STATUS_EB_BIT;
++//                            u32 eb = (status & eb_mask) >> DMA_STATUS_EB_BIT;
++//                            DBG(30, KERN_INFO "int_handler() %s: Bus error 0x%x\n", dev->name, eb);
++                restart_watchdog = 1;
++            }
++
++            if (restart_watchdog) {
++                // Restart the link/PHY state watchdog immediately, which will
++                // attempt to restart the system
++                mod_timer(&priv->watchdog_timer, jiffies);
++                restart_watchdog = 0;
++            }
 +        }
 +
-+        // Should keep a record of the skb that we haven't been able to queue
-+        // for transmission and queue it as soon as a descriptor becomes free
-+        priv->tx_pending_skb = skb;
-+        priv->tx_pending_fragment_count = fragment_count;
++        if (unlikely(restart_tx)) {
++            // Restart the transmitter
++            DBG(35, KERN_INFO "int_handler() %s: Restarting transmitter\n", dev->name);
++            dma_reg_set_mask(priv, DMA_OP_MODE_REG, (1UL << DMA_OP_MODE_ST_BIT));
++        }
 +
-+        // Copy the fragment info to the allocated storage
-+        memcpy(priv->tx_pending_fragments, fragments, sizeof(tx_frag_info_t) * fragment_count);
++        if (unlikely(poll_tx)) {
++            // Issue a TX poll demand in an attempt to restart TX descriptor
++            // processing
++            DBG(33, KERN_INFO "int_handler() %s: Issuing Tx poll demand\n", dev->name);
++            dma_reg_write(priv, DMA_TX_POLL_REG, 0);
++        }
 +
-+        // Stop further calls to hard_start_xmit() until some descriptors are
-+        // freed up by already queued TX packets being completed
-+        netif_stop_queue(dev);
-+    } else {
-+        // Record start of transmission, so timeouts will work once they're
-+        // implemented
-+        dev->trans_start = jiffies;
++        // Read the record of current interrupt requests again, in case some
++        // more arrived while we were processing
++        raw_status = dma_reg_read(priv, DMA_STATUS_REG);
++
++        // MMC, PMT and GLI interrupts are not masked by the interrupt enable
++        // register, so must deal with them on the raw status
++        if (unlikely(raw_status & ((1UL << DMA_STATUS_GPI_BIT) |
++                                   (1UL << DMA_STATUS_GMI_BIT) |
++                                   (1UL << DMA_STATUS_GLI_BIT))))  {
++            process_non_dma_ints(raw_status);
++        }
 +
-+        // Poke the transmitter to look for available TX descriptors, as we have
-+        // just added one, in case it had previously found there were no more
-+        // pending transmission
-+        dma_reg_write(priv, DMA_TX_POLL_REG, 0);
++        // Get status of enabled interrupt sources.
++        status = raw_status & int_enable;
 +    }
 +
-+    spin_unlock_irqrestore(&priv->tx_spinlock_, irq_flags);
-+
-+    return NETDEV_TX_OK;
++    return IRQ_HANDLED;
 +}
-+#endif // CONFIG_LEON_COPRO && CONFIG_LEON_OFFLOAD_TX
++#endif // CONFIG_LEON_COPRO 
 +
-+static struct net_device_stats *get_stats(struct net_device *dev)
-+{
-+    gmac_priv_t* priv = (gmac_priv_t*)netdev_priv(dev);
-+    return &priv->stats;
-+}
++#ifdef CONFIG_LEON_COPRO
++static struct semaphore copro_stop_semaphore;
 +
-+#ifdef CONFIG_NET_POLL_CONTROLLER
-+/**
-+ * Polling 'interrupt' - used by things like netconsole to send skbs without
-+ * having to re-enable interrupts. It's not called while the interrupt routine
-+ * is executing.
-+ */
-+static void netpoll(struct net_device *netdev)
++static void copro_stop_callback(volatile gmac_cmd_que_ent_t* entry)
 +{
-+    disable_irq(netdev->irq);
-+    int_handler(netdev->irq, netdev, NULL);
-+    enable_irq(netdev->irq);
++    up(&copro_stop_semaphore);
 +}
-+#endif // CONFIG_NET_POLL_CONTROLLER
++#endif // CONFIG_LEON_COPRO
 +
-+static int probe(
-+    struct net_device *netdev,
-+    u32                vaddr,
-+    u32                irq,
-+    int                copro_a_irq,
-+    int                copro_b_irq)
++static void gmac_down(struct net_device *dev)
 +{
-+    int err = 0;
-+    u32 version;
-+    int i;
-+    unsigned synopsis_version;
-+    unsigned vendor_version;
-+    gmac_priv_t* priv = netdev_priv(netdev);
-+      u32 reg_contents;
-+
-+    // Ensure the MAC block is properly reset
-+    writel(1UL << SYS_CTRL_RSTEN_MAC_BIT, SYS_CTRL_RSTEN_SET_CTRL);
-+    writel(1UL << SYS_CTRL_RSTEN_MAC_BIT, SYS_CTRL_RSTEN_CLR_CTRL);
++    gmac_priv_t* priv = (gmac_priv_t*)netdev_priv(dev);
++    int desc;
++    u32 int_enable;
++#ifdef CONFIG_LEON_COPRO
++    tx_que_t *tx_queue = &priv->tx_queue_;
++    int cmd_queue_result;
++#endif // CONFIG_LEON_COPRO
 +
-+    // Enable the clock to the MAC block
-+    writel(1UL << SYS_CTRL_CKEN_MAC_BIT, SYS_CTRL_CKEN_SET_CTRL);
++      // Stop NAPI
++      napi_disable(&priv->napi_struct);
 +
-+    // Ensure reset and clock operations are complete
-+    wmb();
++    // Stop further TX packets being delivered to hard_start_xmit();
++    netif_stop_queue(dev);
++    netif_carrier_off(dev);
 +
-+    // Ensure all of the device private data are zero, so we can clean up in
-+    // the event of a later failure to initialise all fields
-+    priv = (gmac_priv_t*)netdev_priv(netdev);
-+    memset(priv, 0, sizeof(gmac_priv_t));
++    // Disable all GMAC interrupts and wait for change to be acknowledged
++    gmac_int_en_clr(priv, ~0UL, &int_enable, 0);
 +
-+    // No debug messages allowed
-+    priv->msg_level = 0UL;
++#ifdef CONFIG_LEON_COPRO
++    // Tell the CoPro to stop network offload operations
++    cmd_queue_result = -1;
++    while (cmd_queue_result) {
++        spin_lock(&priv->cmd_que_lock_);
++        cmd_queue_result = cmd_que_queue_cmd(&priv->cmd_queue_, GMAC_CMD_STOP, 0, copro_stop_callback);
++        spin_unlock(&priv->cmd_que_lock_);
++    }
 +
-+    // Initialise the ISR/hard_start_xmit() lock
-+    spin_lock_init(&priv->tx_spinlock_);
-+    
-+    // Initialise the PHY access lock
-+    spin_lock_init(&priv->phy_lock);
++    // Interrupt the CoPro so it sees the new command
++    writel(1UL << COPRO_SEM_INT_CMD, SYS_CTRL_SEMA_SET_CTRL);
 +
-+    // Set hardware device base addresses
-+    priv->macBase = vaddr + MAC_BASE_OFFSET;
-+    priv->dmaBase = vaddr + DMA_BASE_OFFSET;
++    // Wait until the CoPro acknowledges the STOP command
++    down_interruptible(&copro_stop_semaphore);
 +
-+    // Initialise IRQ ownership to not owned
-+    priv->have_irq = 0;
++    // Wait until the CoPro acknowledges that it has completed stopping
++    down_interruptible(&priv->copro_stop_complete_semaphore_);
 +
-+    // Lock protecting access to CoPro command queue functions or direct access
-+    // to the GMAC interrupt enable register if CoPro is not in use
-+    spin_lock_init(&priv->cmd_que_lock_);
++    // Clear out the Tx offload job queue, deallocating associated resources
++    while (tx_que_not_empty(tx_queue)) {
++        // Free any dynamic fragment ptr/len storage
++        /** @todo */
++        tx_que_inc_r_ptr(tx_queue);
++    }
 +
-+#ifdef CONFIG_LEON_COPRO
-+    sema_init(&copro_stop_semaphore, 0);
-+    sema_init(&copro_start_semaphore, 0);
-+    sema_init(&copro_int_clr_semaphore, 0);
-+    sema_init(&copro_update_semaphore, 0);
-+    sema_init(&copro_rx_enable_semaphore, 0);
-+    priv->copro_a_irq_alloced_ = 0;
-+    priv->copro_b_irq_alloced_ = 0;
-+    sema_init(&priv->copro_stop_complete_semaphore_, 0);
-+    INIT_LIST_HEAD(&priv->copro_tx_skb_list_);
-+    priv->copro_tx_skb_list_count_ = 0;
-+#endif // CONFIG_LEON_COPRO
++    // Reinitialise the Tx offload queue metadata
++    tx_que_init(
++        &priv->tx_queue_,
++        (gmac_tx_que_ent_t*)descriptors_phys_to_virt(priv->copro_params_.tx_que_head_),
++        priv->copro_tx_que_num_entries_);
 +
-+    init_timer(&priv->watchdog_timer);
-+    priv->watchdog_timer.function = &watchdog_timer_action;
-+    priv->watchdog_timer.data = (unsigned long)priv;
++    // Empty the pending SKB queue
++    while (!list_empty(&priv->copro_tx_skb_list_)) {
++        struct sk_buff *skb;
 +
-+    // Set pointer to device in private data
-+    priv->netdev = netdev;
++        // Remove the first entry on the list
++        struct list_head *entry = priv->copro_tx_skb_list_.next;
++        BUG_ON(!entry);
++        list_del(entry);
 +
-+    /** Do something here to detect the present or otherwise of the MAC
-+     *  Read the version register as a first test */
-+    version = mac_reg_read(priv, MAC_VERSION_REG);
-+    synopsis_version = version & 0xff;
-+    vendor_version   = (version >> 8) & 0xff;
++        // Get pointer to SKB from it's list_head member
++        skb = list_entry(entry, struct sk_buff, cb);
++        BUG_ON(!skb);
 +
-+    /** Assume device is at the adr and irq specified until have probing working */
-+    netdev->base_addr  = vaddr;
-+    netdev->irq        = irq;
-+#ifdef CONFIG_LEON_COPRO
-+    priv->copro_a_irq_ = copro_a_irq;
-+    priv->copro_b_irq_ = copro_b_irq;
++        // Inform the network stack that we've finished with the packet
++        dev_kfree_skb(skb);
++    }
++    priv->copro_tx_skb_list_count_ =  0;
 +#endif // CONFIG_LEON_COPRO
 +
-+#ifdef CONFIG_LEON_COPRO
-+    // Allocate the CoPro A IRQ
-+    err = request_irq(priv->copro_a_irq_, &copro_sema_intr, 0, "SEMA", netdev);
-+    if (err) {
-+        DBG(1, KERN_ERR "probe() %s: Failed to allocate CoPro irq A (%d)\n", netdev->name, priv->copro_a_irq_);
-+        goto probe_err_out;
++#ifndef CONFIG_LEON_OFFLOAD_TX
++    // Stop transmitter, take ownership of all tx descriptors
++    dma_reg_clear_mask(priv, DMA_OP_MODE_REG, 1UL << DMA_OP_MODE_ST_BIT);
++    if (priv->desc_vaddr) {
++        tx_take_ownership(&priv->tx_gmac_desc_list_info);
 +    }
-+    // Release the CoPro A IRQ again, as open()/stop() should manage IRQ ownership
-+    free_irq(priv->copro_a_irq_, netdev);
++#endif // !CONFIG_LEON_OFFLOAD_TX
 +
-+    // Allocate the CoPro B IRQ
-+    err = request_irq(priv->copro_b_irq_, &copro_semb_intr, 0, "SEMB", netdev);
-+    if (err) {
-+        DBG(1, KERN_ERR "probe() %s: Failed to allocate CoPro irq B (%d)\n", netdev->name, priv->copro_b_irq_);
-+        goto probe_err_out;
++    // Stop receiver, waiting until it's really stopped and then take ownership
++    // of all rx descriptors
++    change_rx_enable(priv, 0, 1, 0);
++
++    if (priv->desc_vaddr) {
++        rx_take_ownership(&priv->rx_gmac_desc_list_info);
 +    }
-+    // Release the CoPro B IRQ again, as open()/stop() should manage IRQ ownership
-+    free_irq(priv->copro_b_irq_, netdev);
-+#else // CONFIG_LEON_COPRO
-+    // Allocate the IRQ
-+    err = request_irq(netdev->irq, &int_handler, 0, netdev->name, netdev);
-+    if (err) {
-+        DBG(1, KERN_ERR "probe() %s: Failed to allocate irq %d\n", netdev->name, netdev->irq);
-+        goto probe_err_out;
++
++    // Stop all timers
++    delete_watchdog_timer(priv);
++
++    if (priv->desc_vaddr) {
++        // Free receive descriptors
++        do {
++            int first_last = 0;
++            rx_frag_info_t frag_info;
++
++            desc = get_rx_descriptor(priv, &first_last, 0, &frag_info);
++            if (desc >= 0) {
++                              if (unlikely(priv->rx_buffers_per_page)) {
++                                      // If this is the last packet in the page, release the DMA mapping
++                                      unmap_rx_page(priv, frag_info.phys_adr);
++                                      put_page(frag_info.page);
++                              } else {
++                    // Release the DMA mapping for the packet buffer
++                    dma_unmap_single(0, frag_info.phys_adr, frag_info.length, DMA_FROM_DEVICE);
++
++                    // Free the skb
++                    dev_kfree_skb((struct sk_buff *)frag_info.page);
++                              }
++            }
++        } while (desc >= 0);
++
++        // Free transmit descriptors
++        do {
++            struct sk_buff *skb;
++            tx_frag_info_t  frag_info;
++            int             buffer_owned;
++
++            desc = get_tx_descriptor(priv, &skb, 0, &frag_info, &buffer_owned);
++            if (desc >= 0) {
++                if (buffer_owned) {
++                    // Release the DMA mapping for the packet buffer
++                    dma_unmap_single(0, frag_info.phys_adr, frag_info.length, DMA_FROM_DEVICE);
++                }
++
++                if (skb) {
++                    // Free the skb
++                    dev_kfree_skb(skb);
++                }
++            }
++        } while (desc >= 0);
++
++        // Free any resources associated with the buffers of a pending packet
++        if (priv->tx_pending_fragment_count) {
++            tx_frag_info_t *frag_info = priv->tx_pending_fragments;
++
++            while (priv->tx_pending_fragment_count--) {
++                dma_unmap_single(0, frag_info->phys_adr, frag_info->length, DMA_FROM_DEVICE);
++                ++frag_info;
++            }
++        }
++
++        // Free the socket buffer of a pending packet
++        if (priv->tx_pending_skb) {
++            dev_kfree_skb(priv->tx_pending_skb);
++            priv->tx_pending_skb = 0;
++        }
 +    }
 +
-+    // Release the IRQ again, as open()/stop() should manage IRQ ownership
-+    free_irq(netdev->irq, netdev);
-+#endif // CONFIG_LEON_COPRO
++    // Power down the PHY
++    phy_powerdown(dev);
++}
 +
-+    // Initialise the ethernet device with std. contents
-+    ether_setup(netdev);
++static int stop(struct net_device *dev)
++{
++    gmac_priv_t* priv = (gmac_priv_t*)netdev_priv(dev);
 +
-+    // Tell the kernel of our MAC address
-+      for (i = 0; i < netdev->addr_len; i++) {
-+              netdev->dev_addr[i] = (unsigned char)mac_adr[i];
-+      }
++    gmac_down(dev);
 +
-+    // Setup operations pointers
-+    netdev->open               = &open;
-+    netdev->hard_start_xmit    = &hard_start_xmit;
-+    netdev->stop               = &stop;
-+    netdev->get_stats          = &get_stats;
-+    netdev->change_mtu         = &change_mtu;
-+#ifdef CONFIG_NET_POLL_CONTROLLER
-+    netdev->poll_controller    = &netpoll;
-+#endif // CONFIG_NET_POLL_CONTROLLER
-+    netdev->set_mac_address    = &set_mac_address;
-+    netdev->set_multicast_list = &set_multicast_list;
++#ifdef CONFIG_LEON_COPRO
++    shutdown_copro();
 +
-+      // Initialise NAPI support
-+      netif_napi_add(netdev, &priv->napi_struct, &poll, NAPI_POLL_WEIGHT);
++    if (priv->shared_copro_params_) {
++        // Free the DMA coherent parameter space
++        dma_free_coherent(0, sizeof(copro_params_t), priv->shared_copro_params_, priv->shared_copro_params_pa_);
++        priv->shared_copro_params_ = 0;
++    }
 +
-+    set_ethtool_ops(netdev);
++    // Disable semaphore register from causing ARM interrupts
++    *((volatile unsigned long*)SYS_CTRL_SEMA_MASKA_CTRL) = 0;
++    *((volatile unsigned long*)SYS_CTRL_SEMA_MASKB_CTRL) = 0;
 +
-+    if (debug) {
-+      netdev->flags |= IFF_DEBUG;
++    // Release interrupts lines used by semaphore register interrupts
++    if (priv->copro_a_irq_alloced_) {
++        free_irq(priv->copro_a_irq_, dev);
++        priv->copro_a_irq_alloced_ = 0;
 +    }
++    if (priv->copro_b_irq_alloced_) {
++        free_irq(priv->copro_b_irq_, dev);
++        priv->copro_b_irq_alloced_ = 0;
++    }
++#endif // CONFIG_LEON_COPRO 
 +
-+#if defined(CONFIG_LEON_COPRO) && defined(CONFIG_LEON_OFFLOAD_TSO)
-+    // Do TX H/W checksum and SG list processing
-+    netdev->features |= NETIF_F_HW_CSUM;
-+    netdev->features |= NETIF_F_SG;
++      // Free the shadow descriptor memory
++      kfree(priv->tx_desc_shadow_);
++      priv->tx_desc_shadow_ = 0;
 +
-+    // Do hardware TCP/IP Segmentation Offload
-+    netdev->features |= NETIF_F_TSO;
-+#elif !defined(CONFIG_LEON_COPRO) && !defined(CONFIG_HIPOX_VERSION_0X800)
-+    // Do TX H/W checksum and SG list processing
-+    netdev->features |= NETIF_F_HW_CSUM;
-+    netdev->features |= NETIF_F_SG;
-+#endif // USE_TX_CSUM
++      kfree(priv->rx_desc_shadow_);
++      priv->rx_desc_shadow_ = 0;
 +
-+    // We take care of our own TX locking
-+    netdev->features |= NETIF_F_LLTX;
++    // Release the IRQ
++    if (priv->have_irq) {
++        free_irq(dev->irq, dev);
++        priv->have_irq = 0;
++    }
 +
-+    // Initialise PHY support
-+    priv->mii.phy_id_mask   = 0x1f;
-+    priv->mii.reg_num_mask  = 0x1f;
-+    priv->mii.force_media   = 0;
-+    priv->mii.full_duplex   = 1;
-+    priv->mii.using_100     = 0;
-+    priv->mii.using_1000    = 1;
-+      priv->mii.using_pause   = 1;
-+    priv->mii.dev           = netdev;
-+    priv->mii.mdio_read     = phy_read;
-+    priv->mii.mdio_write    = phy_write;
++    // Disable the clock to the MAC block
++    writel(1UL << SYS_CTRL_CKEN_MAC_BIT, SYS_CTRL_CKEN_CLR_CTRL);
 +
-+    priv->gmii_csr_clk_range = 5;   // Slowest for now
++      // Free the sysfs resources
++      kobject_del(&priv->link_state_kobject);
++      subsystem_unregister(&priv->link_state_kset);
 +
-+    // Use simple mux for 25/125 Mhz clock switching and
-+    // enable GMII_GTXCLK to follow GMII_REFCLK - required for gigabit PHY
-+      reg_contents = readl(SYS_CTRL_GMAC_CTRL);
-+      reg_contents |= ((1UL << SYS_CTRL_GMAC_SIMPLE_MAX) |
-+                                        (1UL << SYS_CTRL_GMAC_CKEN_GTX));
-+    writel(reg_contents, SYS_CTRL_GMAC_CTRL);
++    return 0;
++}
 +
-+    // Remember whether auto-negotiation is allowed
-+#ifdef ALLOW_AUTONEG
-+    priv->ethtool_cmd.autoneg = 1;
-+      priv->ethtool_pauseparam.autoneg = 1;
-+#else // ALLOW_AUTONEG
-+    priv->ethtool_cmd.autoneg = 0;
-+      priv->ethtool_pauseparam.autoneg = 0;
-+#endif // ALLOW_AUTONEG
++static void hw_set_mac_address(struct net_device *dev, unsigned char* addr)
++{
++    u32 mac_lo;
++    u32 mac_hi;
 +
-+    // Set up PHY mode for when auto-negotiation is not allowed
-+    priv->ethtool_cmd.speed = SPEED_1000;
-+    priv->ethtool_cmd.duplex = DUPLEX_FULL;
-+    priv->ethtool_cmd.port = PORT_MII;
-+    priv->ethtool_cmd.transceiver = XCVR_INTERNAL;
++    mac_lo  =  (u32)addr[0];
++    mac_lo |= ((u32)addr[1] << 8);
++    mac_lo |= ((u32)addr[2] << 16);
++    mac_lo |= ((u32)addr[3] << 24);
 +
-+#ifndef CONFIG_HIPOX_VERSION_0X800
-+      // We can support both reception and generation of pause frames
-+      priv->ethtool_pauseparam.rx_pause = 1;
-+      priv->ethtool_pauseparam.tx_pause = 1;
-+#endif // !CONFIG_HIPOX_VERSION_0X800
++    mac_hi  =  (u32)addr[4];
++    mac_hi |= ((u32)addr[5] << 8);
 +
-+    // Initialise the set of features we would like to advertise as being
-+      // available for negotiation
-+    priv->ethtool_cmd.advertising = (ADVERTISED_10baseT_Half |
-+                                     ADVERTISED_10baseT_Full |
-+                                     ADVERTISED_100baseT_Half |
-+                                     ADVERTISED_100baseT_Full |
-+#if !defined(CONFIG_HIPOX_VERSION_0X800) || defined(ALLOW_OX800_1000M)
-+                                     ADVERTISED_1000baseT_Half |
-+                                     ADVERTISED_1000baseT_Full |
-+                                                                        ADVERTISED_Pause |
-+                                                                        ADVERTISED_Asym_Pause |
-+#endif
-+                                     ADVERTISED_Autoneg |
-+                                     ADVERTISED_MII);
++    mac_reg_write(netdev_priv(dev), MAC_ADR0_LOW_REG, mac_lo);
++    mac_reg_write(netdev_priv(dev), MAC_ADR0_HIGH_REG, mac_hi);
++}
 +
-+    // Attempt to locate the PHY
-+    phy_detect(netdev);
-+    priv->ethtool_cmd.phy_address = priv->mii.phy_id;
++static int set_mac_address(struct net_device *dev, void *p)
++{
++    struct sockaddr *addr = p;
 +
-+    // Did we find a PHY?
-+      if (priv->phy_type == PHY_TYPE_NONE) {
-+              printk(KERN_WARNING "%s: No PHY found\n", netdev->name);
-+              err = ENXIO;
-+              goto probe_err_out;
++    if (!is_valid_ether_addr(addr->sa_data)) {
++        return -EADDRNOTAVAIL;
 +    }
 +
-+      // Setup the PHY
-+      initialise_phy(priv);
++    memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
++    hw_set_mac_address(dev, addr->sa_data);
 +
-+      // Find out what modes the PHY supports
-+      priv->ethtool_cmd.supported = get_phy_capabilies(priv);
-+#if defined(CONFIG_HIPOX_VERSION_0X800) && !defined(ALLOW_OX800_1000M)
-+      // OX800 has broken 1000M support in the MAC
-+      priv->ethtool_cmd.supported &= ~(SUPPORTED_1000baseT_Full | SUPPORTED_1000baseT_Half);
-+#endif
++    return 0;
++}
 +
-+    // Register the device with the network intrastructure
-+    err = register_netdev(netdev);
-+    if (err) {
-+        DBG(1, KERN_ERR "probe() %s: Failed to register device\n", netdev->name);
-+        goto probe_err_out;
-+    }
++static void multicast_hash(struct dev_mc_list *dmi, u32 *hash_lo, u32 *hash_hi)
++{
++    u32 crc = ether_crc_le(dmi->dmi_addrlen, dmi->dmi_addr);
++    u32 mask = 1 << ((crc >> 26) & 0x1F);
 +
-+    // Record details about the hardware we found
-+    printk(KERN_NOTICE "%s: GMAC ver = %u, vendor ver = %u at 0x%lx, IRQ %d\n", netdev->name, synopsis_version, vendor_version, netdev->base_addr, netdev->irq);
-+#ifndef ARMULATING
-+    printk(KERN_NOTICE "%s: Found PHY at address %u, type 0x%08x -> %s\n", priv->netdev->name, priv->phy_addr, priv->phy_type, (priv->ethtool_cmd.supported & SUPPORTED_1000baseT_Full) ? "10/100/1000" : "10/100");
-+#endif // !ARMULATING
-+    printk(KERN_NOTICE "%s: Ethernet addr: ", priv->netdev->name);
-+    for (i = 0; i < 5; i++) {
-+        printk("%02x:", netdev->dev_addr[i]);
++    if (crc >> 31) {
++        *hash_hi |= mask;
++    } else {
++        *hash_lo |= mask;
 +    }
-+    printk("%02x\n", netdev->dev_addr[5]);
++}
 +
-+#ifdef CONFIG_LEON_COPRO
-+    // Define sizes of queues for communicating with the CoPro
-+    priv->copro_cmd_que_num_entries_ = COPRO_CMD_QUEUE_NUM_ENTRIES;
-+    priv->copro_tx_que_num_entries_ = COPRO_TX_QUEUE_NUM_ENTRIES;
-+#endif // CONFIG_LEON_COPRO 
++static void set_multicast_list(struct net_device *dev)
++{
++    gmac_priv_t* priv = netdev_priv(dev);
++    u32 hash_lo=0;
++    u32 hash_hi=0;
++    u32 mode = 0;
++    int i;
 +
-+      // Initialise sysfs for link state reporting
-+      err = gmac_link_state_init_sysfs(priv);
-+      if (err) {
-+        DBG(1, KERN_ERR "probe() %s: Failed to initialise sysfs support\n", netdev->name);
-+        goto probe_err_out;
-+      }
++    // Disable promiscuous mode and uni/multi-cast matching
++    mac_reg_write(priv, MAC_FRAME_FILTER_REG, mode);
 +
-+      // Initialise the work queue entry to be used to issue hotplug events to userspace
-+      INIT_WORK(&priv->link_state_change_work, work_handler);
++    // Disable all perfect match registers
++    for (i=0; i < NUM_PERFECT_MATCH_REGISTERS; ++i) {
++        mac_adrhi_reg_write(priv, i, 0);
++    }
 +
-+    return 0;
++    // Promiscuous mode overrides all-multi which overrides other filtering
++    if (dev->flags & IFF_PROMISC) {
++        mode |= (1 << MAC_FRAME_FILTER_PR_BIT);
++    } else if (dev->flags & IFF_ALLMULTI) {
++        mode |= (1 << MAC_FRAME_FILTER_PM_BIT);
++    } else {
++        struct dev_mc_list *dmi;
 +
-+probe_err_out:
-+#ifdef CONFIG_LEON_COPRO 
-+    shutdown_copro();
++        if (dev->mc_count <= NUM_PERFECT_MATCH_REGISTERS) {
++            // Use perfect matching registers
++            for (i=0, dmi = dev->mc_list; dmi; dmi = dmi->next, ++i) {
++                u32 addr;
 +
-+    if (priv->shared_copro_params_) {
-+        // Free the DMA coherent parameter space
-+        dma_free_coherent(0, sizeof(copro_params_t), priv->shared_copro_params_, priv->shared_copro_params_pa_);
-+        priv->shared_copro_params_ = 0;
++                addr  =      dmi->dmi_addr[0];
++                addr |= (u32)dmi->dmi_addr[1] << 8;
++                addr |= (u32)dmi->dmi_addr[2] << 16;
++                addr |= (u32)dmi->dmi_addr[3] << 24;
++                mac_adrlo_reg_write(priv, i, addr);
++
++                addr  =      dmi->dmi_addr[4];
++                addr |= (u32)dmi->dmi_addr[5] << 8;
++                addr |= (1 << MAC_ADR1_HIGH_AE_BIT);
++                mac_adrhi_reg_write(priv, i, addr);
++            }
++        } else {
++            // Use hashing
++            mode |= (1 << MAC_FRAME_FILTER_HUC_BIT);
++            mode |= (1 << MAC_FRAME_FILTER_HMC_BIT);
++
++            for (dmi = dev->mc_list; dmi; dmi = dmi->next) {
++                multicast_hash(dmi, &hash_lo, &hash_hi);
++            }
++        }
 +    }
-+#endif // CONFIG_LEON_COPRO 
 +
-+    // Disable the clock to the MAC block
-+    writel(1UL << SYS_CTRL_CKEN_MAC_BIT, SYS_CTRL_CKEN_CLR_CTRL);
++    // Update the filtering rules
++    mac_reg_write(priv, MAC_FRAME_FILTER_REG, mode);
 +
-+    return err;
++    // Update the filtering hash table
++    mac_reg_write(priv, MAC_HASH_LOW_REG,  hash_lo);
++    mac_reg_write(priv, MAC_HASH_HIGH_REG, hash_hi);
 +}
 +
-+static int gmac_found_count = 0;
-+static struct net_device* gmac_netdev[MAX_GMAC_UNITS];
-+
-+/**
-+ * External entry point to the driver, called from Space.c to detect a card
-+ */
-+struct net_device* __init synopsys_gmac_probe(int unit)
++static int gmac_up(struct net_device *dev)
 +{
-+    int err = 0;
-+    struct net_device *netdev = alloc_etherdev(sizeof(gmac_priv_t));
-+
-+    printk(KERN_NOTICE "Probing for Synopsis GMAC, unit %d\n", unit);
++    int status = 0;
++    gmac_priv_t *priv = (gmac_priv_t*)netdev_priv(dev);
++    u32 reg_contents;
++#ifdef CONFIG_LEON_COPRO
++    int cmd_queue_result;
++#endif // CONFIG_LEON_COPRO
 +
-+    // Will allocate private data later, as may want descriptors etc in special memory
-+    if (!netdev) {
-+        printk(KERN_WARNING "synopsys_gmac_probe() failed to alloc device\n");
-+        err = -ENODEV;
-+    } else {
-+        if (unit >= 0) {
-+            sprintf(netdev->name, "eth%d", unit);
++    // Reset the entire GMAC
++    dma_reg_write(priv, DMA_BUS_MODE_REG, 1UL << DMA_BUS_MODE_SWR_BIT);
 +
-+            netdev_boot_setup_check(netdev);
++    // Ensure reset is performed before testing for completion
++    wmb();
 +
-+            if (gmac_found_count >= MAX_GMAC_UNITS) {
-+                err = -ENODEV;
-+            } else {
-+                err = probe(netdev, MAC_BASE, MAC_INTERRUPT, SEM_A_INTERRUPT, SEM_B_INTERRUPT);
-+                if (err) {
-+                    printk(KERN_WARNING "synopsys_gmac_probe() Probing failed for %s\n", netdev->name);
-+                } else {
-+                    ++gmac_found_count;
-+                }
-+            }
++    // Wait for the reset operation to complete
++    status = -EIO;
++      printk(KERN_INFO "Resetting GMAC\n");
++    for (;;) {
++        if (!(dma_reg_read(priv, DMA_BUS_MODE_REG) & (1UL << DMA_BUS_MODE_SWR_BIT))) {
++            status = 0;
++            break;
 +        }
++    }
 +
-+        if (err) {
-+            netdev->reg_state = NETREG_UNREGISTERED;
-+            free_netdev(netdev);
-+        } else {
-+                      gmac_netdev[unit] = netdev;
-+              }
++    // Did the GMAC reset operation fail?
++    if (status) {
++        printk(KERN_ERR "open() %s: GMAC reset failed\n", dev->name);
++        goto gmac_up_err_out;
 +    }
++      printk(KERN_INFO "GMAC reset complete\n");
 +
-+    return ERR_PTR(err);
-+}
++      /* Initialise MAC config register contents
++       */
++    reg_contents = 0;
++    if (!priv->mii.using_1000) {
++        DBG(1, KERN_INFO "open() %s: PHY in 10/100Mb mode\n", dev->name);
++        reg_contents |= (1UL << MAC_CONFIG_PS_BIT);
++    } else {
++        DBG(1, KERN_INFO "open() %s: PHY in 1000Mb mode\n", dev->name);
++    }
++    if (priv->mii.full_duplex) {
++        reg_contents |= (1UL << MAC_CONFIG_DM_BIT);
++    }
 +
-+static int __init gmac_module_init(void)
-+{
-+      return (int)synopsys_gmac_probe(0);
-+}
-+module_init(gmac_module_init);
++#ifdef USE_RX_CSUM
++      reg_contents |= (1UL << MAC_CONFIG_IPC_BIT);
++#endif // USE_RX_CSUM
 +
-+static void __exit gmac_module_cleanup(void)
-+{
-+      int i;
-+      for (i=0; i < gmac_found_count; i++) {
-+              stop(gmac_netdev[i]);
-+              gmac_netdev[i]->reg_state = NETREG_UNREGISTERED;
-+              free_netdev(gmac_netdev[i]);
++    if (priv->jumbo_) {
++              // Allow passage of jumbo frames through both transmitter and receiver
++              reg_contents |= ((1UL << MAC_CONFIG_JE_BIT) |
++                        (1UL << MAC_CONFIG_JD_BIT) |
++                                               (1UL << MAC_CONFIG_WD_BIT));
 +      }
-+}
-+module_exit(gmac_module_cleanup);
-+
-diff -Nurd linux-2.6.24/arch/arm/mach-hipox/gmac.h linux-2.6.24-oxe810/arch/arm/mach-hipox/gmac.h
---- linux-2.6.24/arch/arm/mach-hipox/gmac.h    1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mach-hipox/gmac.h     2008-06-11 17:47:55.000000000 +0200
-@@ -0,0 +1,194 @@
-+/*
-+ * linux/arch/arm/mach-hipox/gmac.h
-+ *
-+ * Copyright (C) 2005 Oxford Semiconductor Ltd
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+#if !defined(__GMAC_H__)
-+#define __GMAC_H__
-+
-+#include <asm/semaphore.h>
-+#include <asm/types.h>
-+#include <linux/mii.h>
-+#include <linux/netdevice.h>
-+#include <linux/spinlock.h>
-+#include <linux/workqueue.h>
-+#include <linux/list.h>
-+#include <linux/ethtool.h>
-+#include <linux/kobject.h>
-+#include <asm/arch/desc_alloc.h>
-+#include <asm/arch/dma.h>
-+#ifdef CONFIG_LEON_COPRO
-+#include <asm/arch/leon.h>
-+#include "gmac_offload.h"
-+#endif // CONFIG_LEON_COPRO
 +
-+#ifdef GMAC_DEBUG
-+#define DBG(n, args...)\
-+    do {\
-+        if ((n) <= priv->msg_level)\
-+            printk(args);\
-+    } while (0)
-+#else
-+#define DBG(n, args...)   do { } while(0)
-+#endif
++      // Enable transmitter and receiver
++    reg_contents |= ((1UL << MAC_CONFIG_TE_BIT) |
++                     (1UL << MAC_CONFIG_RE_BIT));
 +
-+#define MS_TO_JIFFIES(x) (((x) < (1000/(HZ))) ? 1 : (x) * (HZ) / 1000)
++      // Select the minimum IFG - I found that 80 bit times caused very poor
++      // IOZone performance, so stcik with the 96 bit times default
++      reg_contents |= (0UL << MAC_CONFIG_IFG_BIT);
 +
-+#define USE_RX_CSUM
-+//#define ARMULATING
++    // Write MAC config setup to the GMAC
++    mac_reg_write(priv, MAC_CONFIG_REG, reg_contents);
 +
-+typedef struct gmac_desc_list_info {
-+    volatile gmac_dma_desc_t *base_ptr;
-+    gmac_dma_desc_t          *shadow_ptr;
-+    int                       num_descriptors;
-+    int                       empty_count;
-+    int                       full_count;
-+    int                       r_index;
-+    int                       w_index;
-+} gmac_desc_list_info_t;
++      /* Initialise MAC VLAN register contents
++       */
++    reg_contents = 0;
++    mac_reg_write(priv, MAC_VLAN_TAG_REG, reg_contents);
 +
-+#ifdef CONFIG_LEON_COPRO
-+typedef struct copro_params {
-+    u32 cmd_que_head_;
-+    u32 cmd_que_tail_;
-+    u32 fwd_intrs_mailbox_;
-+    u32 tx_que_head_;
-+    u32 tx_que_tail_;
-+    u32 free_start_;
-+    u32 mtu_;
-+    u32 rx_mitigation_;
-+    u32 rx_mitigation_frames_;
-+    u32 rx_mitigation_usec_;
-+} __attribute ((aligned(4),packed)) copro_params_t;
-+#endif // CONFIG_LEON_COPRO
++    // Initialise the hardware's record of our primary MAC address
++    hw_set_mac_address(dev, dev->dev_addr);
 +
-+typedef struct tx_frag_info {
-+    dma_addr_t  phys_adr;
-+    u16         length;
-+} tx_frag_info_t;
++    // Initialise multicast and promiscuous modes
++    set_multicast_list(dev);
 +
-+// Private data structure for the GMAC driver
-+typedef struct gmac_priv {
-+    /** Base address of GMAC MAC registers */
-+    u32                       macBase;
-+    /** Base address of GMAC DMA registers */
-+    u32                       dmaBase;
++    // Disable all MMC interrupt sources
++    mac_reg_write(priv, MMC_RX_MASK_REG, ~0UL);
++    mac_reg_write(priv, MMC_TX_MASK_REG, ~0UL);
 +
-+    struct net_device*        netdev;
++    // Remember how large the unified descriptor array is to be
++    priv->total_num_descriptors = NUM_TX_DMA_DESCRIPTORS + NUM_RX_DMA_DESCRIPTORS;
 +
-+    struct net_device_stats   stats;
++    // Initialise the structures managing the TX descriptor list
++    init_tx_desc_list(&priv->tx_gmac_desc_list_info,
++                      priv->desc_vaddr,
++                      priv->tx_desc_shadow_,
++                      NUM_TX_DMA_DESCRIPTORS);
 +
-+    u32                       msg_level;
-+    
-+    /** Whether we own an IRQ */
-+    int                       have_irq;
++    // Initialise the structures managing the RX descriptor list
++    init_rx_desc_list(&priv->rx_gmac_desc_list_info,
++                      priv->desc_vaddr + NUM_TX_DMA_DESCRIPTORS,
++                      priv->rx_desc_shadow_,
++                      NUM_RX_DMA_DESCRIPTORS,
++                      priv->rx_buffer_size_);
 +
-+    /** Pointer to outstanding tx packet that has not yet been queued due to
-+     *  lack of descriptors */
-+    struct sk_buff           *tx_pending_skb;
-+    tx_frag_info_t            tx_pending_fragments[18];
-+    int                       tx_pending_fragment_count;
++    // Reset record of pending Tx packet
++    priv->tx_pending_skb = 0;
++    priv->tx_pending_fragment_count = 0;
 +
-+    /** DMA consistent physical address of outstanding tx packet */
-+    dma_addr_t                tx_pending_dma_addr;
-+    unsigned long             tx_pending_length;
++#ifndef CONFIG_LEON_OFFLOAD_TX
++    // Write the physical DMA consistent address of the start of the tx descriptor array
++    dma_reg_write(priv, DMA_TX_DESC_ADR_REG, priv->desc_dma_addr);
++#endif // !CONFIG_LEON_OFFLOAD_TX
 +
-+    /** To synchronise ISR and thread TX activities' access to private data */
-+    spinlock_t                tx_spinlock_;
++    // Write the physical DMA consistent address of the start of the rx descriptor array
++    dma_reg_write(priv, DMA_RX_DESC_ADR_REG, priv->desc_dma_addr +
++                        (priv->tx_gmac_desc_list_info.num_descriptors * sizeof(gmac_dma_desc_t)));
 +
-+    /** To synchronise access to the PHY */
-+    spinlock_t                phy_lock;
++    // Initialise the GMAC DMA bus mode register
++    dma_reg_write(priv, DMA_BUS_MODE_REG, ((1UL << DMA_BUS_MODE_FB_BIT)   |   // Force bursts
++                                           (8UL << DMA_BUS_MODE_PBL_BIT)  |   // AHB burst size
++                                           (1UL << DMA_BUS_MODE_DA_BIT)));    // Round robin Rx/Tx
 +
-+    /** The timer for NAPI polling when out of memory when trying to fill RX
-+     *  descriptor ring */
++    // Prepare receive descriptors
++    refill_rx_ring(dev);
 +
-+    /** PHY related info */
-+    struct mii_if_info        mii;
-+    struct ethtool_cmd        ethtool_cmd;
-+      struct ethtool_pauseparam ethtool_pauseparam;
-+    u32                       phy_addr;
-+    u32                       phy_type;
-+    int                       gmii_csr_clk_range;
++    // Clear any pending interrupt requests
++    dma_reg_write(priv, DMA_STATUS_REG, dma_reg_read(priv, DMA_STATUS_REG));
 +
-+    /** Periodic timer to check link status etc */
-+    struct timer_list         watchdog_timer;
-+    volatile int              watchdog_timer_shutdown;
++      /* Initialise flow control register contents
++       */
++      // Enable Rx flow control
++    reg_contents = (1UL << MAC_FLOW_CNTL_RFE_BIT);
 +
-+    /** The number of descriptors in the gmac_dma_desc_t array holding both the TX and
-+     *  RX descriptors. The TX descriptors reside at the start of the array */
-+    unsigned                  total_num_descriptors;
-+    /** The CPU accessible virtual address of the start of the descriptor array */
-+    gmac_dma_desc_t*          desc_vaddr;
-+    /** The hardware accessible physical address of the start of the descriptor array */
-+    dma_addr_t                desc_dma_addr;
++#ifndef CONFIG_HIPOX_VERSION_0X800
++      if (priv->mii.using_pause) {
++              // Enable Tx flow control
++              reg_contents |= (1UL << MAC_FLOW_CNTL_TFE_BIT);
++      }
 +
-+    /** Descriptor list management */
-+    gmac_desc_list_info_t     tx_gmac_desc_list_info;
-+    gmac_desc_list_info_t     rx_gmac_desc_list_info;
-+    
-+    /** Record of disabling RX overflow interrupts */
-+    unsigned                  rx_overflow_ints_disabled;
++    // Set the duration of the pause frames generated by the transmitter when
++      // the Rx fifo fill threshold is exceeded
++      reg_contents |= ((0x100UL << MAC_FLOW_CNTL_PT_BIT) |    // Pause for 256 slots
++                                        (0x1UL << MAC_FLOW_CNTL_PLT_BIT));
++#endif // !CONFIG_HIPOX_VERSION_0X800
 +
-+    /** The result of the last H/W DMA generated checksum operation */
-+    u16                       tx_csum_result_;
++      // Write flow control setup to the GMAC
++    mac_reg_write(priv, MAC_FLOW_CNTL_REG, reg_contents);
 +
-+    /** Whether we deal in jumbo frames */
-+    int                       jumbo_;
++      /* Initialise operation mode register contents
++       */
++    // Initialise the GMAC DMA operation mode register. Set Tx/Rx FIFO thresholds
++    // to make best use of our limited SDRAM bandwidth when operating in gigabit
++      reg_contents = ((DMA_OP_MODE_TTC_256 << DMA_OP_MODE_TTC_BIT) |    // Tx threshold
++                    (1UL << DMA_OP_MODE_FUF_BIT) |                                            // Forward Undersized good Frames
++                    (DMA_OP_MODE_RTC_128 << DMA_OP_MODE_RTC_BIT) |    // Rx threshold 128 bytes
++                    (1UL << DMA_OP_MODE_OSF_BIT));                                            // Operate on 2nd frame
 +
-+    volatile int              mii_init_media;
-+    volatile int              phy_force_negotiation;
++#ifndef CONFIG_HIPOX_VERSION_0X800
++      // Enable hardware flow control
++      reg_contents |= (1UL << DMA_OP_MODE_EFC_BIT);
 +
-+#ifdef CONFIG_LEON_COPRO
-+    /** DMA coherent memory for CoPro's parameter storage */
-+    copro_params_t  *shared_copro_params_;
-+    dma_addr_t       shared_copro_params_pa_;
++      // Set threshold for enabling hardware flow control at (full-4KB) to give
++      // space for upto two in-flight std MTU packets to arrive after pause frame
++      // has been sent.
++      reg_contents |= ((0UL << DMA_OP_MODE_RFA2_BIT) |
++                                        (3UL << DMA_OP_MODE_RFA_BIT));
 +
-+    /** ARM's local CoPro parameter storage */
-+    copro_params_t   copro_params_;
++      // Set threshold for disabling hardware flow control (-7KB)
++      reg_contents |= ((1UL << DMA_OP_MODE_RFD2_BIT) |
++                                        (2UL << DMA_OP_MODE_RFD_BIT));
 +
-+    /** Queue for commands/acks to/from CoPro */
-+    int              copro_a_irq_;
-+    int              copro_a_irq_alloced_;
-+    int              copro_b_irq_;
-+    int              copro_b_irq_alloced_;
-+    cmd_que_t        cmd_queue_;
-+    tx_que_t         tx_queue_;
-+    int              copro_cmd_que_num_entries_;
-+    int              copro_tx_que_num_entries_;
-+      struct semaphore copro_stop_complete_semaphore_;
-+      struct list_head copro_tx_skb_list_;
-+      int                              copro_tx_skb_list_count_;
-+#endif // CONFIG_LEON_COPRO
++    // Don't flush Rx frames from FIFO just because there's no descriptor available
++      reg_contents |= (1UL << DMA_OP_MODE_DFF_BIT);
++#endif // !CONFIG_HIPOX_VERSION_0X800
 +
-+    spinlock_t       cmd_que_lock_;
-+      u32                               rx_buffer_size_;
-+      int                               rx_buffers_per_page;
++      // Write settings to operation mode register
++    dma_reg_write(priv, DMA_OP_MODE_REG, reg_contents);
 +
-+      gmac_dma_desc_t *tx_desc_shadow_;
-+      gmac_dma_desc_t *rx_desc_shadow_;
++#ifdef CONFIG_HIPOX_VERSION_0X800
++    // Use store&forward when operating in gigabit mode, as OX800 does not have
++    // sufficient SDRAM bandwidth to support gigabit Tx without it and OX800
++      // does not support Tx checksumming in the GMAC
++    if (priv->mii.using_1000) {
++        dma_reg_set_mask(priv, DMA_OP_MODE_REG, (1UL << DMA_OP_MODE_SF_BIT));
++    } else {
++        dma_reg_clear_mask(priv, DMA_OP_MODE_REG, (1UL << DMA_OP_MODE_SF_BIT));
++    }
++#else // CONFIG_HIPOX_VERSION_0X800
++    // GMAC requires store&forward in order to compute Tx checksums
++    dma_reg_set_mask(priv, DMA_OP_MODE_REG, (1UL << DMA_OP_MODE_SF_BIT));
++#endif // CONFIG_HIPOX_VERSION_0X800
 +
-+      struct napi_struct napi_struct;
++    // Ensure setup is complete, before enabling TX and RX
++    wmb();
 +
-+      /** sysfs dir tree root for recovery button driver */
-+      struct kset        link_state_kset;
-+      struct kobject     link_state_kobject;
-+      struct work_struct link_state_change_work;
-+      int                link_state;
-+} gmac_priv_t;
++#ifdef CONFIG_LEON_COPRO
++    // Update the CoPro's parameters with the current MTU
++    priv->copro_params_.mtu_ = dev->mtu;
 +
-+#endif        //  #if !defined(__GMAC_H__)
++    // Only attempt to write to uncached/unbuffered shared parameter storage if
++    // CoPro is started and thus storage has been allocated
++    if (priv->shared_copro_params_) {
++        // Fill the CoPro parameter block
++        memcpy(priv->shared_copro_params_, &priv->copro_params_, sizeof(copro_params_t));
++    }
 +
-diff -Nurd linux-2.6.24/arch/arm/mach-hipox/gmac_desc.c linux-2.6.24-oxe810/arch/arm/mach-hipox/gmac_desc.c
---- linux-2.6.24/arch/arm/mach-hipox/gmac_desc.c       1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mach-hipox/gmac_desc.c        2008-06-11 17:47:55.000000000 +0200
-@@ -0,0 +1,452 @@
-+/*
-+ * linux/arch/arm/mach-hipox/gmac_desc.c
-+ *
-+ * Copyright (C) 2005 Oxford Semiconductor Ltd
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+#include <linux/delay.h>
++    // Make sure the CoPro parameter block updates have made it to memory (which
++    // is uncached/unbuffered, so just compiler issues to overcome)
++    wmb();
 +
-+//#define GMAC_DEBUG
-+#undef GMAC_DEBUG
++    // Tell the CoPro to re-read parameters
++    cmd_queue_result = -1;
++    while (cmd_queue_result) {
++        spin_lock(&priv->cmd_que_lock_);
++        cmd_queue_result = cmd_que_queue_cmd(&priv->cmd_queue_, GMAC_CMD_UPDATE_PARAMS, 0, copro_update_callback);
++        spin_unlock(&priv->cmd_que_lock_);
++    }
 +
-+#include "gmac.h"
-+#include "gmac_desc.h"
++    // Interrupt the CoPro so it sees the new command
++    writel(1UL << COPRO_SEM_INT_CMD, SYS_CTRL_SEMA_SET_CTRL);
 +
-+void init_rx_desc_list(
-+    gmac_desc_list_info_t    *desc_list,
-+    volatile gmac_dma_desc_t *base_ptr,
-+      gmac_dma_desc_t          *shadow_ptr,
-+    int                       num_descriptors,
-+      u16                       rx_buffer_length)
-+{
-+    int i;
++    // Wait until the CoPro acknowledges that the update of parameters is complete
++    down_interruptible(&copro_update_semaphore);
 +
-+    desc_list->base_ptr = base_ptr;
-+    desc_list->shadow_ptr = shadow_ptr;
-+    desc_list->num_descriptors = num_descriptors;
-+    desc_list->empty_count = num_descriptors;
-+    desc_list->full_count = 0;
-+    desc_list->r_index = 0;
-+    desc_list->w_index = 0;
++    // Tell the CoPro to begin network offload operations
++    cmd_queue_result = -1;
++    while (cmd_queue_result) {
++        spin_lock(&priv->cmd_que_lock_);
++        cmd_queue_result = cmd_que_queue_cmd(&priv->cmd_queue_, GMAC_CMD_START, 0, copro_start_callback);
++        spin_unlock(&priv->cmd_que_lock_);
++    }
 +
-+      for (i=0; i < num_descriptors; ++i) {
-+              gmac_dma_desc_t          *shadow = shadow_ptr + i;
-+              volatile gmac_dma_desc_t *desc   = base_ptr + i;
++    // Interrupt the CoPro so it sees the new command
++    writel(1UL << COPRO_SEM_INT_CMD, SYS_CTRL_SEMA_SET_CTRL);
 +
-+              // Initialise the shadow descriptor
-+              shadow->status = 0;
-+              shadow->length = (rx_buffer_length << RDES1_RBS1_BIT);
-+              if (i == (num_descriptors - 1)) {
-+                      shadow->length |= (1UL << RDES1_RER_BIT);
-+              }
-+              shadow->buffer1 = 0;
-+              shadow->buffer2 = 0;
++    // Wait until the CoPro acknowledges that it has started
++    down_interruptible(&copro_start_semaphore);
++#endif // CONFIG_LEON_COPRO
 +
-+              // Copy the shadow descriptor into the real descriptor
-+              desc->status  = shadow->status;
-+              desc->length  = shadow->length;
-+              desc->buffer1 = shadow->buffer1;
-+              desc->buffer2 = shadow->buffer2;
-+      }
-+}
++      // Start NAPI
++      napi_enable(&priv->napi_struct);
 +
-+void init_tx_desc_list(
-+    gmac_desc_list_info_t    *desc_list,
-+    volatile gmac_dma_desc_t *base_ptr,
-+      gmac_dma_desc_t          *shadow_ptr,
-+    int                       num_descriptors)
-+{
-+    int i;
++    // Start the transmitter and receiver
++#ifndef CONFIG_LEON_OFFLOAD_TX
++    dma_reg_set_mask(priv, DMA_OP_MODE_REG, (1UL << DMA_OP_MODE_ST_BIT));
++#endif // !LEON_OFFLOAD_TX
++    change_rx_enable(priv, 1, 0, 0);
 +
-+    desc_list->base_ptr = base_ptr;
-+    desc_list->shadow_ptr = shadow_ptr;
-+    desc_list->num_descriptors = num_descriptors;
-+    desc_list->empty_count = num_descriptors;
-+    desc_list->full_count = 0;
-+    desc_list->r_index = 0;
-+    desc_list->w_index = 0;
++    // Enable interesting GMAC interrupts
++    gmac_int_en_set(priv, ((1UL << DMA_INT_ENABLE_NI_BIT)  |
++                           (1UL << DMA_INT_ENABLE_AI_BIT)  |
++                           (1UL << DMA_INT_ENABLE_FBE_BIT) |
++                           (1UL << DMA_INT_ENABLE_RI_BIT)  |
++                           (1UL << DMA_INT_ENABLE_RU_BIT)  |
++                           (1UL << DMA_INT_ENABLE_OV_BIT)  |
++                           (1UL << DMA_INT_ENABLE_RW_BIT)  |
++                           (1UL << DMA_INT_ENABLE_RS_BIT)  |
++                           (1UL << DMA_INT_ENABLE_TI_BIT)  |
++                           (1UL << DMA_INT_ENABLE_UN_BIT)  |
++                           (1UL << DMA_INT_ENABLE_TJ_BIT)  |
++                           (1UL << DMA_INT_ENABLE_TS_BIT)));
 +
-+      for (i=0; i < num_descriptors; ++i) {
-+              gmac_dma_desc_t          *shadow = shadow_ptr + i;
-+              volatile gmac_dma_desc_t *desc   = base_ptr + i;
++    // (Re)start the link/PHY state monitoring timer
++    start_watchdog_timer(priv);
 +
-+              // Initialise the shadow descriptor
-+              shadow->status = 0;
-+              shadow->length = (1UL << TDES1_IC_BIT);
-+              if (i == (num_descriptors - 1)) {
-+                      shadow->length |= (1UL << TDES1_TER_BIT);
-+              }
-+              shadow->buffer1 = 0;
-+              shadow->buffer2 = 0;
++    // Allow the network stack to call hard_start_xmit()
++    netif_start_queue(dev);
 +
-+              // Copy the shadow descriptor into the real descriptor
-+              desc->status  = shadow->status;
-+              desc->length  = shadow->length;
-+              desc->buffer1 = shadow->buffer1;
-+              desc->buffer2 = shadow->buffer2;
-+      }
-+}
++#ifdef DUMP_REGS_ON_GMAC_UP
++    dump_mac_regs(priv->macBase, priv->dmaBase);
++#endif // DUMP_REGS_ON_GMAC_UP
 +
-+void rx_take_ownership(gmac_desc_list_info_t* desc_list)
-+{
-+    int i;
-+    for (i=0; i < desc_list->num_descriptors; ++i) {
-+        (desc_list->base_ptr + i)->status &= ~(1UL << RDES0_OWN_BIT);
-+    }
++    return status;
 +
-+    // Ensure all write to the descriptor shared with MAC have completed
-+    wmb();
++gmac_up_err_out:
++    stop(dev);
++
++    return status;
 +}
 +
-+void tx_take_ownership(gmac_desc_list_info_t* desc_list)
++static void set_rx_packet_info(struct net_device *dev)
 +{
-+    int i;
-+    for (i=0; i < desc_list->num_descriptors; ++i) {
-+        (desc_list->base_ptr + i)->status &= ~(1UL << TDES0_OWN_BIT);
-+    }
++    gmac_priv_t *priv = (gmac_priv_t*)netdev_priv(dev);
++      int max_packet_buffer_size = dev->mtu + EXTRA_RX_SKB_SPACE;
 +
-+    // Ensure all write to the descriptor shared with MAC have completed
-+    wmb();
++      if (max_packet_buffer_size > max_descriptor_length()) {
++#ifndef RX_BUFFER_SIZE
++              priv->rx_buffer_size_ = max_packet_buffer_size;
++#else // !RX_BUFFER_SIZE
++              priv->rx_buffer_size_ = RX_BUFFER_SIZE;
++#endif // ! RX_BUFFER_SIZE
++              priv->rx_buffers_per_page = GMAC_ALLOC_SIZE / (priv->rx_buffer_size_ + NET_IP_ALIGN);
++      } else {
++              priv->rx_buffer_size_ = max_packet_buffer_size;
++              priv->rx_buffers_per_page = 0;
++      }
 +}
 +
-+int set_rx_descriptor(
-+    gmac_priv_t    *priv,
-+    rx_frag_info_t *frag_info)
++static int change_mtu(struct net_device *dev, int new_mtu)
 +{
-+    int index = -1;
-+
-+    // Is there a Rx descriptor available for writing by the CPU?
-+    if (available_for_write(&priv->rx_gmac_desc_list_info)) {
-+        // Setup the descriptor required to describe the RX packet
-+        volatile gmac_dma_desc_t *descriptor;
-+        gmac_dma_desc_t          *shadow;
++    int status = 0;
++    gmac_priv_t *priv = (gmac_priv_t*)netdev_priv(dev);
++    int original_mtu = dev->mtu;
 +
-+        // Get the index of the next RX descriptor available for writing by the CPU
-+        index = priv->rx_gmac_desc_list_info.w_index;
++    // Check that new MTU is within supported range
++    if ((new_mtu < MIN_PACKET_SIZE) || (new_mtu > MAX_JUMBO)) {
++        DBG(1, KERN_WARNING "change_mtu() %s: Invalid MTU %d\n", dev->name, new_mtu);
++        status = -EINVAL;
++    } else {
++        // Put MAC/PHY into quiesent state, causing all current buffers to be
++        // deallocated and the PHY to powerdown
++        gmac_down(dev);
 +
-+        // Get a pointer to the next RX descriptor available for writing by the CPU
-+        descriptor = priv->rx_gmac_desc_list_info.base_ptr   + index;
-+        shadow     = priv->rx_gmac_desc_list_info.shadow_ptr + index;
++        // Record the new MTU, so bringing the MAC back up will allocate
++        // resources to suit the new MTU
++        dev->mtu = new_mtu;
 +
-+        // Set first buffer pointer to buffer from skb
-+        descriptor->buffer1 = shadow->buffer1 = frag_info->phys_adr;
++              // Set length etc. of rx packets
++              set_rx_packet_info(dev);
 +
-+        // Remember the skb associated with the buffer
-+        shadow->buffer2 = (u32)frag_info->page;
++        // Reset the PHY to get it into a known state and ensure we have TX/RX
++        // clocks to allow the GMAC reset to complete
++        if (phy_reset(priv->netdev)) {
++            DBG(1, KERN_ERR "change_mtu() %s: Failed to reset PHY\n", dev->name);
++            status = -EIO;
++        } else {
++                      // Set PHY specfic features
++                      initialise_phy(priv);
 +
-+        // Ensure all prior writes to the descriptor shared with MAC have
-+        // completed before setting the descriptor ownership flag to transfer
-+        // ownership to the GMAC
-+        wmb();
++            // Record whether jumbo frames should be enabled
++            priv->jumbo_ = (dev->mtu > NORMAL_PACKET_SIZE);
 +
-+        // Set RX descriptor status to transfer ownership to the GMAC
-+        descriptor->status = (1UL << RDES0_OWN_BIT);
++            // Force or auto-negotiate PHY mode
++            priv->phy_force_negotiation = 1;
 +
-+        // Update the index of the next descriptor available for writing by the CPU
-+        priv->rx_gmac_desc_list_info.w_index = (shadow->length & (1UL << RDES1_RER_BIT)) ? 0 : index + 1;
++            // Reallocate buffers with new MTU
++            gmac_up(dev);
++        }
++    }
 +
-+        // Account for the descriptor used to hold the new packet
-+        --priv->rx_gmac_desc_list_info.empty_count;
-+        ++priv->rx_gmac_desc_list_info.full_count;
++    // If there was a failure
++    if (status) {
++        // Return the MTU to its original value
++        DBG(1, KERN_INFO "change_mtu() Failed, returning MTU to original value\n");
++        dev->mtu = original_mtu;
 +    }
 +
-+    return index;
++    return status;
 +}
 +
-+int get_rx_descriptor(
-+    gmac_priv_t    *priv,
-+    int            *last,
-+    u32            *status,
-+    rx_frag_info_t *frag_info)
-+{
-+      int                       index;
-+      volatile gmac_dma_desc_t *descriptor;
-+      gmac_dma_desc_t          *shadow;
-+      u32                       desc_status;
++#ifdef TEST_COPRO
++DECLARE_MUTEX_LOCKED(start_sem);
++DECLARE_MUTEX_LOCKED(heartbeat_sem);
 +
-+      if (!priv->rx_gmac_desc_list_info.full_count) {
-+              return -2;
-+      }
++void start_callback(volatile gmac_cmd_que_ent_t* entry)
++{
++    printk("START callback, operand = 0x%08x\n", entry->operand_);
++    up(&start_sem);
++}
 +
-+      // Get the index of the descriptor released the longest time ago by the GMAC DMA 
-+    index       = priv->rx_gmac_desc_list_info.r_index;
-+      descriptor  = priv->rx_gmac_desc_list_info.base_ptr   + index;
-+      shadow      = priv->rx_gmac_desc_list_info.shadow_ptr + index;
++void heartbeat_callback(volatile gmac_cmd_que_ent_t* entry)
++{
++    printk("Heartbeat callback, operand = 0x%08x\n", entry->operand_);
++    up(&heartbeat_sem);
++}
 +
-+      if (status && *status) {
-+              desc_status = *status;
-+      } else {
-+              desc_status = descriptor->status;
-+      }
++static void test_copro(gmac_priv_t* priv)
++{
++    unsigned long irq_flags;
 +
-+    if (desc_status & (1UL << RDES0_OWN_BIT)) {
-+              return -1;
-+      }
++    spin_lock(&priv->cmd_que_lock_);
++    cmd_que_queue_cmd(&priv->cmd_queue_, GMAC_CMD_STOP, 0, 0);
++    spin_unlock(&priv->cmd_que_lock_);
++    writel(1UL << COPRO_SEM_INT_CMD, SYS_CTRL_SEMA_SET_CTRL);
++    mdelay(500);
 +
-+      // Update the index of the next descriptor with which the GMAC DMA may have finished
-+      priv->rx_gmac_desc_list_info.r_index = (shadow->length & (1UL << RDES1_RER_BIT)) ? 0 : index + 1;
++    spin_lock(&priv->cmd_que_lock_);
++    cmd_que_queue_cmd(&priv->cmd_queue_, GMAC_CMD_START, 0, start_callback);
++    spin_unlock(&priv->cmd_que_lock_);
++    writel(1UL << COPRO_SEM_INT_CMD, SYS_CTRL_SEMA_SET_CTRL);
++    mdelay(500);
 +
-+      // Account for the descriptor which is now no longer waiting to be processed by the CPU
-+      ++priv->rx_gmac_desc_list_info.empty_count;
-+      --priv->rx_gmac_desc_list_info.full_count;
++    spin_lock(&priv->cmd_que_lock_);
++    cmd_que_queue_cmd(&priv->cmd_queue_, GMAC_CMD_HEARTBEAT, 0, heartbeat_callback);
++    spin_unlock(&priv->cmd_que_lock_);
++    writel(1UL << COPRO_SEM_INT_CMD, SYS_CTRL_SEMA_SET_CTRL);
++    mdelay(500);
 +
-+      // Get packet details from the descriptor
-+      frag_info->page = (struct page*)(shadow->buffer2);
-+      frag_info->phys_adr = shadow->buffer1;
-+      frag_info->length = get_rx_length(desc_status);
++    printk("Waiting for start ack...\n");
++    down_interruptible(&start_sem);
++    printk("Start ack received\n");
 +
-+      // Is this descriptor the last contributing to a packet
-+      *last = desc_status & (1UL << RDES0_LS_BIT);
++    printk("Waiting for heartbeat ack...\n");
++    down_interruptible(&heartbeat_sem);
++    printk("Heartbeat ack received\n");
++}
++#endif // TEST_COPRO
 +
-+      // Accumulate the status
-+      if (status && !*status) {
-+              *status = desc_status;
-+      }
++#ifdef CONFIG_LEON_COPRO 
++#define SEM_INT_FWD      8
++#define SEM_INT_ACK      16
++#define SEM_INT_TX       17
++#define SEM_INT_STOP_ACK 18
 +
-+    return index;
-+}
++#define SEM_INTA_MASK  (1UL << SEM_INT_FWD)
++#define SEM_INTB_MASK ((1UL << SEM_INT_ACK) | (1UL << SEM_INT_TX) | (1UL << SEM_INT_STOP_ACK))
 +
-+static inline int num_descriptors_needed(u16 length)
++static irqreturn_t copro_sema_intr(int irq, void *dev_id)
 +{
-+      static const int GMAC_MAX_DESC_ORDER = 11;
-+      static const u16 GMAC_MAX_DESC_MASK = ((1 << (GMAC_MAX_DESC_ORDER)) - 1);
++    struct net_device *dev = (struct net_device *)dev_id;
++    gmac_priv_t       *priv = (gmac_priv_t*)netdev_priv(dev);
++    u32                asserted;
++    u32                fwd_intrs_status = 0;
++    int                is_fwd_intr;
 +
-+      int count = length >> GMAC_MAX_DESC_ORDER;
-+      if (length & GMAC_MAX_DESC_MASK) {
-+              ++count;
-+      }
-+      if ((count * max_descriptor_length()) < length) {
-+              ++count;
-+      }
++    // Read the contents of semaphore A register
++    asserted = (*((volatile unsigned long*)SYS_CTRL_SEMA_STAT) & SEM_INTA_MASK);
 +
-+      return count;
-+}
++    while (asserted) {
++        // Extract any forwarded interrupts info
++        is_fwd_intr = asserted & (1UL << SEM_INT_FWD);
++        if (is_fwd_intr) {
++            fwd_intrs_status = ((volatile gmac_fwd_intrs_t*)descriptors_phys_to_virt(priv->copro_params_.fwd_intrs_mailbox_))->status_;
++        }
 +
-+int set_tx_descriptor(
-+    gmac_priv_t    *priv,
-+    struct sk_buff *skb,
-+    tx_frag_info_t *frag_info,
-+    int             frag_count,
-+    int             use_hw_csum)
-+{
-+      int first_descriptor_index = -1;
-+      int num_descriptors = frag_count;
-+    int frag_index = 0;
-+      int check_oversized_frags = priv->netdev->mtu >= (max_descriptor_length() - ETH_HLEN);
++        // Clear any interrupts directed at the ARM
++        *((volatile unsigned long*)SYS_CTRL_SEMA_CLR_CTRL) = asserted;
 +
-+      if (unlikely(check_oversized_frags)) {
-+              // Calculate the number of extra descriptors required due to fragments
-+              // being longer than the maximum buffer size that can be described by a
-+              // single descriptor
-+              num_descriptors = 0;
-+              do {
-+                      // How many descriptors are required to describe the fragment?
-+                      num_descriptors += num_descriptors_needed(frag_info[frag_index].length);
-+              } while (++frag_index < frag_count);
-+      }
++        if (is_fwd_intr) {
++            // Process any forwarded GMAC interrupts
++            copro_fwd_intrs_handler(dev_id, fwd_intrs_status);
++        }
 +
-+    // Are sufficicent descriptors available for writing by the CPU?
-+    if (available_for_write(&priv->tx_gmac_desc_list_info) < num_descriptors) {
-+        return -1;
++        // Stay in interrupt routine if interrupt has been re-asserted
++        asserted = (*((volatile unsigned long*)SYS_CTRL_SEMA_STAT) & SEM_INTA_MASK);
 +    }
 +
-+      {
-+              volatile gmac_dma_desc_t *previous_descriptor = 0;
-+              gmac_dma_desc_t          *previous_shadow = 0;
-+              volatile gmac_dma_desc_t *descriptors[num_descriptors];
-+              int desc_index = 0;
-+
-+              frag_index = 0;
-+              do {
-+                      int        last_frag   = (frag_index == (frag_count - 1));
-+                      u16        part_length = frag_info[frag_index].length;
-+                      dma_addr_t phys_adr    = frag_info[frag_index].phys_adr;
-+                      int        part        = 0;
-+                      int        parts       = 1;
++    return IRQ_HANDLED;
++}
 +
-+                      if (unlikely(check_oversized_frags)) {
-+                              // How many descriptors are required to describe the fragment?
-+                              parts = num_descriptors_needed(part_length);
-+                      }
++static irqreturn_t copro_semb_intr(int irq, void *dev_id)
++{
++    struct net_device *dev = (struct net_device *)dev_id;
++    gmac_priv_t       *priv = (gmac_priv_t*)netdev_priv(dev);
++    u32                asserted;
 +
-+                      // Setup a descriptor for each part of the fragment that can be
-+                      // described by a single descriptor
-+                      do {
-+                              int                       last_part  = (part == (parts - 1));
-+                              int                       index      = priv->tx_gmac_desc_list_info.w_index;
-+                              volatile gmac_dma_desc_t *descriptor = priv->tx_gmac_desc_list_info.base_ptr + index;
-+                              gmac_dma_desc_t          *shadow     = priv->tx_gmac_desc_list_info.shadow_ptr + index;
-+                              u32                       length     = shadow->length;
-+                              u32                       buffer2    = 0;
++    // Read the contents of semaphore B register
++    asserted = (*((volatile unsigned long*)SYS_CTRL_SEMA_STAT) & SEM_INTB_MASK);
 +
-+                              // Remember descriptor pointer for final passing of ownership to GMAC
-+                              descriptors[desc_index++] = descriptor;
++    while (asserted) {
++        // Clear any interrupts directed at the ARM
++        *((volatile unsigned long*)SYS_CTRL_SEMA_CLR_CTRL) = asserted;
 +
-+                              // May have a second chained descriptor, but never a second buffer,
-+                              // so clear the flag indicating whether there is a chained descriptor
-+                              length &= ~(1UL << TDES1_TCH_BIT);
++        // Process any outstanding command acknowledgements
++        if (asserted & (1UL << SEM_INT_ACK)) {
++            while (!cmd_que_dequeue_ack(&priv->cmd_queue_));
++        }
 +
-+                              // Clear the first/last descriptor flags
-+                              length &= ~((1UL << TDES1_LS_BIT) | (1UL << TDES1_FS_BIT));
++        // Process STOP completion signal
++        if (asserted & (1UL << SEM_INT_STOP_ACK)) {
++            up(&priv->copro_stop_complete_semaphore_);
++        }
 +
-+                              // Set the Tx checksum mode
-+                              length &= ~(((1UL << TDES1_CIC_NUM_BITS) - 1) << TDES1_CIC_BIT);
-+                              if (use_hw_csum) {
-+                                      // Don't want full mode as network stack will have already
-+                                      // computed the TCP/UCP pseudo header and placed in into the
-+                                      // TCP/UCP checksum field
-+                                      length |= (TDES1_CIC_PAYLOAD << TDES1_CIC_BIT);
-+                              }
-+                              // Set fragment buffer length
-+                              length &= ~(((1UL << TDES1_TBS1_NUM_BITS) - 1) << TDES1_TBS1_BIT);
-+                              length |= ((part_length > max_descriptor_length() ? max_descriptor_length() : part_length) << TDES1_TBS1_BIT);
++#ifdef CONFIG_LEON_OFFLOAD_TX
++        // Process any completed TX offload jobs
++        if (asserted & (1UL << SEM_INT_TX)) {
++            finish_xmit(dev);
++        }
++#endif // CONFIG_LEON_OFFLOAD_TX
 +
-+                              // Set fragment buffer address
-+                              descriptor->buffer1 = shadow->buffer1 = phys_adr;
++        // Stay in interrupt routine if interrupt has been re-asserted
++        asserted = (*((volatile unsigned long*)SYS_CTRL_SEMA_STAT) & SEM_INTB_MASK);
++    }
 +
-+                              if (previous_shadow) {
-+                                      // Make the previous descriptor chain to the current one
-+                                      previous_shadow->length |= (1UL << TDES1_TCH_BIT);
-+                                      previous_descriptor->length = previous_shadow->length;
++    return IRQ_HANDLED;
++}
++#endif // CONFIG_LEON_COPRO 
 +
-+                                      previous_shadow->buffer2 |= descriptors_virt_to_phys((u32)descriptor);
-+                                      previous_descriptor->buffer2 = previous_shadow->buffer2;
-+                              }
++static int open(struct net_device *dev)
++{
++    gmac_priv_t* priv = (gmac_priv_t*)netdev_priv(dev);
++    int status;
 +
-+                              // Is this the first desciptor for the packet?
-+                              if (!frag_index && !part) {
-+                                      // Need to return index of first descriptor used for packet
-+                                      first_descriptor_index = index;
++    // Ensure the MAC block is properly reset
++    writel(1UL << SYS_CTRL_RSTEN_MAC_BIT, SYS_CTRL_RSTEN_SET_CTRL);
++    writel(1UL << SYS_CTRL_RSTEN_MAC_BIT, SYS_CTRL_RSTEN_CLR_CTRL);
 +
-+                                      // Set flag indicating is first descriptor for packet
-+                                      length |= (1UL << TDES1_FS_BIT);
-+                              }
++    // Enable the clock to the MAC block
++    writel(1UL << SYS_CTRL_CKEN_MAC_BIT, SYS_CTRL_CKEN_SET_CTRL);
 +
-+                              // Is this the last descriptor for the packet?
-+                              if (last_frag && last_part) {
-+                                      // Store the skb pointer with the last descriptor for packet, in
-+                                      // which the second buffer address will be unused as we do not use
-+                                      // second buffers and only intermedate buffers may use the chained
-+                                      // descriptor address
-+                                      buffer2 = (u32)skb;
++    // Ensure reset and clock operations are complete
++    wmb();
 +
-+                                      // Set flag indicating is last descriptor for packet
-+                                      length |= (1UL << TDES1_LS_BIT);
-+                              } else {
-+                                      // For descriptor chaining need to remember previous descriptor
-+                                      previous_descriptor = descriptor;
-+                                      previous_shadow = shadow;
++    // Reset the PHY to get it into a known state and ensure we have TX/RX clocks
++    // to allow the GMAC reset to complete
++    if (phy_reset(priv->netdev)) {
++        DBG(1, KERN_ERR "open() %s: Failed to reset PHY\n", dev->name);
++        status = -EIO;
++        goto open_err_out;
++    }
 +
-+                                      // Is this descriptor not the last describing a single fragment
-+                                      // buffer?
-+                                      if (!last_part) {
-+                                              // This descriptor does not own the fragment buffer, so use
-+                                              // the (h/w ignored) lsb of buffer2 to encode this info.
-+                                              buffer2 = 1;
++      // Set PHY specfic features
++      initialise_phy(priv);
 +
-+                                              // Update the fragment buffer part details
-+                                              part_length -= max_descriptor_length();
-+                                              phys_adr    += max_descriptor_length();
-+                                      }
-+                              }
++    // Check that the MAC address is valid.  If it's not, refuse to bring the
++    // device up
++    if (!is_valid_ether_addr(dev->dev_addr)) {
++        DBG(1, KERN_ERR "open() %s: MAC address invalid\n", dev->name);
++        status = -EINVAL;
++        goto open_err_out;
++    }
 +
-+                              // Write the assembled length descriptor entry to the descriptor
-+                              descriptor->length = shadow->length = length;
++#ifdef CONFIG_LEON_COPRO 
++    // Register ISRs for the semaphore register interrupt sources, which will
++    // originate from the CoPro
++    if (request_irq(priv->copro_a_irq_, &copro_sema_intr, 0, "SEMA", dev)) {
++        panic("open: Failed to allocate semaphore A %u\n", priv->copro_a_irq_);
++        status = -ENODEV;
++        goto open_err_out;
++    }
++    priv->copro_a_irq_alloced_ = 1;
 +
-+                              // Write the assembled buffer2 descriptor entry to the descriptor
-+                              shadow->buffer2 = buffer2;
++    if (request_irq(priv->copro_b_irq_, &copro_semb_intr, 0, "SEMB", dev)) {
++        panic("open: Failed to allocate semaphore B %u\n", priv->copro_b_irq_);
++        status = -ENODEV;
++        goto open_err_out;
++    }
++    priv->copro_b_irq_alloced_ = 1;
++#else // CONFIG_LEON_COPRO 
++    // Allocate the IRQ
++    if (request_irq(dev->irq, &int_handler, 0, dev->name, dev)) {
++        DBG(1, KERN_ERR "open() %s: Failed to allocate irq %d\n", dev->name, dev->irq);
++        status = -ENODEV;
++        goto open_err_out;
++    }
++    priv->have_irq = 1;
++#endif // CONFIG_LEON_COPRO 
 +
-+                              // Update the index of the next descriptor available for writing by the CPU
-+                              priv->tx_gmac_desc_list_info.w_index = (length & (1UL << TDES1_TER_BIT)) ? 0 : index + 1;
-+                      } while (++part < parts);
-+              } while (++frag_index < frag_count);
++    // Need a consistent DMA mapping covering all the memory occupied by DMA
++    // unified descriptor array, as both CPU and DMA engine will be reading and
++    // writing descriptor fields.
++    priv->desc_vaddr    = (gmac_dma_desc_t*)GMAC_DESC_ALLOC_START;
++    priv->desc_dma_addr = GMAC_DESC_ALLOC_START_PA;
 +
-+              // Ensure all prior writes to the descriptors shared with MAC have
-+              // completed before setting the descriptor ownership flags to transfer
-+              // ownership to the GMAC
-+              wmb();
++    if (!priv->desc_vaddr) {
++        DBG(1, KERN_ERR "open() %s: Failed to allocate consistent memory for DMA descriptors\n", dev->name);
++        status = -ENOMEM;
++        goto open_err_out;
++    }
 +
-+              // Transfer descriptors to GMAC's ownership in reverse order, so when
-+              // GMAC begins processing the first descriptor all others are already
-+              // owned by the GMAC
-+              for (desc_index = (num_descriptors - 1); desc_index >= 0; --desc_index) {
-+                      descriptors[desc_index]->status = (1UL << TDES0_OWN_BIT);
-+              }
++      // Allocate memory to hold shadow of GMAC descriptors
++      if (!(priv->tx_desc_shadow_ = kmalloc(NUM_TX_DMA_DESCRIPTORS * sizeof(gmac_dma_desc_t), GFP_KERNEL))) {
++        DBG(1, KERN_ERR "open() %s: Failed to allocate memory for Tx descriptor shadows\n", dev->name);
++        status = -ENOMEM;
++        goto open_err_out;
++      }
++      if (!(priv->rx_desc_shadow_ = kmalloc(NUM_RX_DMA_DESCRIPTORS * sizeof(gmac_dma_desc_t), GFP_KERNEL))) {
++        DBG(1, KERN_ERR "open() %s: Failed to allocate memory for Rx descriptor shadows\n", dev->name);
++        status = -ENOMEM;
++        goto open_err_out;
 +      }
 +
-+    // Account for the number of descriptors used to hold the new packet
-+    priv->tx_gmac_desc_list_info.empty_count -= (num_descriptors);
-+    priv->tx_gmac_desc_list_info.full_count  += (num_descriptors);
++      // Record whether jumbo frames should be enabled
++    priv->jumbo_ = (dev->mtu > NORMAL_PACKET_SIZE);
 +
-+    return first_descriptor_index;
-+}
++      set_rx_packet_info(dev);
 +
-+int get_tx_descriptor(
-+    gmac_priv_t     *priv,
-+    struct sk_buff **skb,
-+    u32             *status,
-+    tx_frag_info_t  *frag_info,
-+    int             *buffer_owned)
-+{
-+    int index = -1;
-+      u32 local_status;
++#ifdef CONFIG_LEON_COPRO 
++    // Allocate SRAM for the command queue entries
++    priv->copro_params_.cmd_que_head_ = DESCRIPTORS_BASE_PA + DESCRIPTORS_SIZE;
 +
-+    // Find the first available Tx descriptor
-+    if (tx_available_for_read(&priv->tx_gmac_desc_list_info, &local_status)) {
-+        gmac_dma_desc_t *shadow;
-+        u32 length;
-+        u32 buffer2;
++    priv->copro_params_.cmd_que_tail_ =
++        (u32)((gmac_cmd_que_ent_t*)(priv->copro_params_.cmd_que_head_) + priv->copro_cmd_que_num_entries_);
++    priv->copro_params_.fwd_intrs_mailbox_ = priv->copro_params_.cmd_que_tail_;
++    priv->copro_params_.tx_que_head_ = priv->copro_params_.fwd_intrs_mailbox_ + sizeof(gmac_fwd_intrs_t);
++    priv->copro_params_.tx_que_tail_ =
++        (u32)((gmac_tx_que_ent_t*)(priv->copro_params_.tx_que_head_) + priv->copro_tx_que_num_entries_);
++    priv->copro_params_.free_start_ = priv->copro_params_.tx_que_tail_;
 +
-+        // Get the descriptor released the longest time ago by the GMAC DMA
-+        index = priv->tx_gmac_desc_list_info.r_index;
-+        shadow = priv->tx_gmac_desc_list_info.shadow_ptr + index;
++    // Set RX interrupt mitigation behaviour
++    priv->copro_params_.rx_mitigation_        = COPRO_RX_MITIGATION;
++    priv->copro_params_.rx_mitigation_frames_ = COPRO_RX_MITIGATION_FRAMES;
++    priv->copro_params_.rx_mitigation_usec_   = COPRO_RX_MITIGATION_USECS;
++
++    // Initialise command queue metadata
++    cmd_que_init(
++        &priv->cmd_queue_,
++        (gmac_cmd_que_ent_t*)descriptors_phys_to_virt(priv->copro_params_.cmd_que_head_),
++        priv->copro_cmd_que_num_entries_);
++
++    // Initialise tx offload queue metadata
++    tx_que_init(
++        &priv->tx_queue_,
++        (gmac_tx_que_ent_t*)descriptors_phys_to_virt(priv->copro_params_.tx_que_head_),
++        priv->copro_tx_que_num_entries_);
 +
-+        // Get the length of the buffer
-+        length = shadow->length;
-+        frag_info->length = ((length >> TDES1_TBS1_BIT) & ((1UL << TDES1_TBS1_NUM_BITS) - 1));
++    // Allocate DMA coherent space for the parameter block shared with the CoPro
++    priv->shared_copro_params_ = dma_alloc_coherent(0, sizeof(copro_params_t), &priv->shared_copro_params_pa_, GFP_KERNEL);
++    if (!priv->shared_copro_params_) {
++        DBG(1, KERN_ERR "open() %s: Failed to allocate DMA coherent space for parameters\n");
++        status = -ENOMEM;
++        goto open_err_out;
++    }
 +
-+        // Get a pointer to the buffer
-+        frag_info->phys_adr = shadow->buffer1;
++    // Update the CoPro's parameters with the current MTU
++    priv->copro_params_.mtu_ = dev->mtu;
 +
-+              // Get buffer ownership or skb info
-+        buffer2 = shadow->buffer2;
++    // Fill the shared CoPro parameter block from the ARM's local copy
++    memcpy(priv->shared_copro_params_, &priv->copro_params_, sizeof(copro_params_t));
 +
-+        // Check that chained buffer not is use before setting skb from buffer2
-+        if (!(length & (1UL << TDES1_TCH_BIT))) {
-+            *skb = (struct sk_buff*)buffer2;
-+                      *buffer_owned = 1;
-+        } else {
-+            // The lsb (h/w ignored) is used to encode buffer ownership
-+            *buffer_owned = !(buffer2 & 1);
-+                      *skb = 0;
-+        }
++    // Load CoPro program and start it running
++    init_copro(leon_srec, priv->shared_copro_params_pa_);
 +
-+        // Accumulate status
-+        if (status) {
-+            *status |= local_status;
-+        }
++    // Enable selected semaphore register bits to cause ARM interrupts
++    *((volatile unsigned long*)SYS_CTRL_SEMA_MASKA_CTRL) = SEM_INTA_MASK;
++    *((volatile unsigned long*)SYS_CTRL_SEMA_MASKB_CTRL) = SEM_INTB_MASK;
 +
-+        // Update the index of the next descriptor with which the GMAC DMA may have finished
-+        priv->tx_gmac_desc_list_info.r_index = (length & (1UL << TDES1_TER_BIT)) ? 0 : index + 1;
++#ifdef TEST_COPRO
++    // Send test commands to the CoPro
++    test_copro(priv);
++#endif // TEST_COPRO
++#endif // CONFIG_LEON_COPRO 
 +
-+        // Account for the descriptor which is now no longer waiting to be processed by the CPU
-+        ++priv->tx_gmac_desc_list_info.empty_count;
-+        --priv->tx_gmac_desc_list_info.full_count;
++    // Do startup operations that are in common with gmac_down()/_up() processing
++    priv->mii_init_media = 1;
++    priv->phy_force_negotiation = 1;
++    status = gmac_up(dev);
++    if (status) {
++        goto open_err_out;
 +    }
 +
-+    return index;
-+}
++    return 0;
 +
-diff -Nurd linux-2.6.24/arch/arm/mach-hipox/gmac_desc.h linux-2.6.24-oxe810/arch/arm/mach-hipox/gmac_desc.h
---- linux-2.6.24/arch/arm/mach-hipox/gmac_desc.h       1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mach-hipox/gmac_desc.h        2008-06-11 17:47:55.000000000 +0200
-@@ -0,0 +1,315 @@
-+/*
-+ * linux/arch/arm/mach-hipox/gmac_desc.h
-+ *
-+ * Copyright (C) 2005 Oxford Semiconductor Ltd
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+#if !defined(__GMAC_DESC_H__)
-+#define __GMAC_DESC_H__
++open_err_out:
++    stop(dev);
 +
-+#include <asm/types.h>
-+#include "gmac.h"
++    return status;
++}
 +
-+typedef enum rdes0 {
-+    RDES0_OWN_BIT  = 31,
-+    RDES0_AFM_BIT  = 30,
-+    RDES0_FL_BIT   = 16,
-+    RDES0_ES_BIT   = 15,
-+    RDES0_DE_BIT   = 14,
-+    RDES0_SAF_BIT  = 13,
-+    RDES0_LE_BIT   = 12,
-+    RDES0_OE_BIT   = 11,
-+    RDES0_IPC_BIT  = 10,
-+    RDES0_FS_BIT   = 9,
-+    RDES0_LS_BIT   = 8,
-+    RDES0_VLAN_BIT = 7,
-+    RDES0_LC_BIT   = 6,
-+    RDES0_FT_BIT   = 5,
-+    RDES0_RWT_BIT  = 4,
-+    RDES0_RE_BIT   = 3,
-+    RDES0_DRE_BIT  = 2,
-+    RDES0_CE_BIT   = 1,
-+    RDES0_PCE_BIT  = 0
-+} rdes0_t;
++#if defined(CONFIG_LEON_COPRO) && defined(CONFIG_LEON_OFFLOAD_TX)
++static int hard_start_xmit(
++    struct sk_buff *skb,
++    struct net_device *dev)
++{
++    gmac_priv_t                *priv = (gmac_priv_t*)netdev_priv(dev);
++    volatile gmac_tx_que_ent_t *job;
++    unsigned long               irq_flags;
 +
-+#define RX_DESC_STATUS_FL_NUM_BITS 14
++    if (skb_shinfo(skb)->frag_list) {
++        panic("Frag list - can't handle this!\n");
++    }
 +
-+typedef enum rdes1 {
-+    RDES1_DIC_BIT  = 31,
-+    RDES1_RER_BIT  = 25,
-+    RDES1_RCH_BIT  = 24,
-+    RDES1_RBS2_BIT = 11,
-+    RDES1_RBS1_BIT = 0,
-+} rdes1_t;
++    // Protection against concurrent operations in ISR and hard_start_xmit()
++    if (!spin_trylock_irqsave(&priv->tx_spinlock_, irq_flags)) {
++        return NETDEV_TX_LOCKED;
++    }
 +
-+#define RX_DESC_LENGTH_RBS2_NUM_BITS 11
-+#define RX_DESC_LENGTH_RBS1_NUM_BITS 11
++    // NETIF_F_LLTX apparently introduces a potential for hard_start_xmit() to
++    // be called when the queue has been stopped (although I think only in SMP)
++    // so do a check here to make sure we should proceed
++    if (netif_queue_stopped(dev)) {
++        spin_unlock_irqrestore(&priv->tx_spinlock_, irq_flags);
++        return NETDEV_TX_BUSY;
++    }
 +
-+typedef enum tdes0 {
-+    TDES0_OWN_BIT = 31,
-+    TDES0_IHE_BIT = 16,
-+    TDES0_ES_BIT  = 15,
-+    TDES0_JT_BIT  = 14,
-+    TDES0_FF_BIT  = 13,
-+    TDES0_PCE_BIT = 12,
-+    TDES0_LOC_BIT = 11,
-+    TDES0_NC_BIT  = 10,
-+    TDES0_LC_BIT  = 9,
-+    TDES0_EC_BIT  = 8,
-+    TDES0_VF_BIT  = 7,
-+    TDES0_CC_BIT  = 3,
-+    TDES0_ED_BIT  = 2,
-+    TDES0_UF_BIT  = 1,
-+    TDES0_DB_BIT  = 0
-+} tdes0_t;
++    job = tx_que_get_idle_job(dev);
++    if (!job) {
++        // Tx offload queue is full, so add skb to pending skb list
++        list_add_tail((struct list_head*)&skb->cb, &priv->copro_tx_skb_list_);
 +
-+#define TDES0_CC_NUM_BITS 4
++        // Keep track of how many entries are in the pending SKB list
++        ++priv->copro_tx_skb_list_count_;
 +
-+typedef enum tdes1 {
-+    TDES1_IC_BIT   = 31,
-+    TDES1_LS_BIT   = 30,
-+    TDES1_FS_BIT   = 29,
-+    TDES1_CIC_BIT  = 27,
-+    TDES1_DC_BIT   = 26,
-+    TDES1_TER_BIT  = 25,
-+    TDES1_TCH_BIT  = 24,
-+    TDES1_DP_BIT   = 23,
-+    TDES1_TBS2_BIT = 11,
-+    TDES1_TBS1_BIT = 0
-+} tdes1_t;
++        // Have we queued the max allowed number of SKBs?
++        if (priv->copro_tx_skb_list_count_ >= COPRO_MAX_QUEUED_TX_SKBS) {
++            // Stop further calls to hard_start_xmit() until some descriptors
++            // are freed up by already queued TX packets being completed
++            netif_stop_queue(dev);
++        }
++    } else {
++        if (priv->copro_tx_skb_list_count_) {
++            // Have queued pending SKBs, so add new SKB to tail of pending list
++            list_add_tail((struct list_head*)&skb->cb, &priv->copro_tx_skb_list_);
 +
-+#define TDES1_CIC_NUM_BITS  2
-+#define TDES1_TBS2_NUM_BITS 11
-+#define TDES1_TBS1_NUM_BITS 11
++            // Keep track of how many entries are in the pending SKB list
++            ++priv->copro_tx_skb_list_count_;
 +
-+#define TDES1_CIC_NONE    0
-+#define TDES1_CIC_HDR     1
-+#define TDES1_CIC_PAYLOAD 2
-+#define TDES1_CIC_FULL    3
++            // Process pending SKBs, oldest first
++            copro_process_pending_tx_skbs(dev, job);
++        } else {
++            // Fill the Tx offload job with the network packet's details
++            copro_fill_tx_job(job, skb);
 +
-+extern void init_rx_desc_list(
-+    gmac_desc_list_info_t    *desc_list,
-+    volatile gmac_dma_desc_t *base_ptr,
-+      gmac_dma_desc_t          *shadow_ptr,
-+    int                       num_descriptors,
-+      u16                       rx_buffer_length);
++            // Enqueue the new Tx offload job with the CoPro
++            tx_que_new_job(dev, job);
++        }
 +
-+extern void init_tx_desc_list(
-+    gmac_desc_list_info_t    *desc_list,
-+    volatile gmac_dma_desc_t *base_ptr,
-+      gmac_dma_desc_t          *shadow_ptr,
-+    int                       num_descriptors);
++        // Record start of transmission, so timeouts will work once they're
++        // implemented
++        dev->trans_start = jiffies;
 +
-+/** Force ownership of all descriptors in the specified list to being owned by
-+ *  the CPU
-+ */
-+extern void rx_take_ownership(gmac_desc_list_info_t* desc_list);
++        // Interrupt the CoPro to cause it to examine the Tx offload queue
++        wmb();
++        writel(1UL << COPRO_SEM_INT_TX, SYS_CTRL_SEMA_SET_CTRL);
 +
-+/** Force ownership of all descriptors in the specified list to being owned by
-+ *  the CPU
-+ */
-+extern void tx_take_ownership(gmac_desc_list_info_t* desc_list);
++        // If the network stack's Tx queue was stopped and we now have resources
++        // to process more Tx offload jobs
++        if (netif_queue_stopped(dev) &&
++            !tx_que_is_full(&priv->tx_queue_) &&
++            !priv->copro_tx_skb_list_count_) {
++            // Restart the network stack's TX queue
++            netif_wake_queue(dev);
++        }
++    }
 +
-+/** Return the number of descriptors available for the CPU to fill with new
-+ *  packet info */
-+static inline int available_for_write(gmac_desc_list_info_t* desc_list)
++    spin_unlock_irqrestore(&priv->tx_spinlock_, irq_flags);
++
++    return NETDEV_TX_OK;
++}
++#else
++static inline void unmap_fragments(
++    tx_frag_info_t *frags,
++    int             count)
 +{
-+    return desc_list->empty_count;
++    while (count--) {
++        dma_unmap_single(0, frags->phys_adr, frags->length, DMA_TO_DEVICE);
++        ++frags;
++    }
 +}
 +
-+/** Return non-zero if there is a descriptor available with a packet with which
-+ *  the GMAC DMA has finished */
-+static inline int tx_available_for_read(
-+      volatile gmac_desc_list_info_t *desc_list,
-+      u32                            *status)
++static int hard_start_xmit(
++    struct sk_buff    *skb,
++    struct net_device *dev)
 +{
-+      if (!desc_list->full_count) {
-+              return 0;
-+      }
-+
-+      *status = (desc_list->base_ptr + desc_list->r_index)->status;
++    gmac_priv_t            *priv = (gmac_priv_t*)netdev_priv(dev);
++    unsigned long           irq_flags;
++    struct skb_shared_info *shinfo = skb_shinfo(skb);
++    int                     fragment_count = shinfo->nr_frags + 1;
++    tx_frag_info_t          fragments[fragment_count];
++    int                     frag_index;
 +
-+      if (*status & (1UL << TDES0_OWN_BIT)) {
-+              return 0;
-+      }
++    // Get consistent DMA mappings for the SDRAM to be DMAed from by the GMAC,
++    // causing a flush from the CPU's cache to the memory.
 +
-+      return 1;
-+}
++    // Do the DMA mappings before acquiring the tx lock, even though it complicates
++    // the later code, as this can be a long operation involving cache flushing
 +
-+/**
-+ * Return non-zero if there is a descriptor available with a packet with which
-+ * the GMAC DMA has finished.
-+ */
-+static inline int rx_available_for_read(
-+      volatile gmac_desc_list_info_t *desc_list,
-+      u32                            *status)
-+{
-+      u32 local_status;
++    // Map the main buffer
++    fragments[0].length = skb_headlen(skb);
++    fragments[0].phys_adr = dma_map_single(0, skb->data, skb_headlen(skb), DMA_TO_DEVICE);
++    BUG_ON(dma_mapping_error(fragments[0].phys_adr));
 +
-+      if (!desc_list->full_count) {
-+              return 0;
-+      }
++    // Map any SG fragments
++    for (frag_index = 0; frag_index < shinfo->nr_frags; ++frag_index) {
++        skb_frag_t *frag = &shinfo->frags[frag_index];
 +
-+      local_status = (desc_list->base_ptr + desc_list->r_index)->status;
++        fragments[frag_index + 1].length = frag->size;
++        fragments[frag_index + 1].phys_adr = dma_map_page(0, frag->page, frag->page_offset, frag->size, DMA_TO_DEVICE);
++        BUG_ON(dma_mapping_error(fragments[frag_index + 1].phys_adr));
++    }
 +
-+    if (local_status & (1UL << RDES0_OWN_BIT)) {
-+              return 0;
-+      }
++    // Protection against concurrent operations in ISR and hard_start_xmit()
++    if (unlikely(!spin_trylock_irqsave(&priv->tx_spinlock_, irq_flags))) {
++        unmap_fragments(fragments, fragment_count);
++        return NETDEV_TX_LOCKED;
++    }
 +
-+      if (status) {
-+              *status = local_status;
-+      }
++    // NETIF_F_LLTX apparently introduces a potential for hard_start_xmit() to
++    // be called when the queue has been stopped (although I think only in SMP)
++    // so do a check here to make sure we should proceed
++    if (unlikely(netif_queue_stopped(dev))) {
++        unmap_fragments(fragments, fragment_count);
++        spin_unlock_irqrestore(&priv->tx_spinlock_, irq_flags);
++        return NETDEV_TX_BUSY;
++    }
 +
-+    return 1;
-+}
++    // Construct the GMAC DMA descriptor
++    if (unlikely(set_tx_descriptor(priv,
++                          skb,
++                          fragments,
++                          fragment_count,
++                          skb->ip_summed == CHECKSUM_PARTIAL) < 0)) {
++        // Shouldn't see a full ring without the queue having already been
++        // stopped, and the queue should already have been stopped if we have
++        // already queued a single pending packet
++        if (priv->tx_pending_skb) {
++            printk(KERN_WARNING "hard_start_xmit() Ring full and pending packet already queued\n");
++            unmap_fragments(fragments, fragment_count);
++            spin_unlock_irqrestore(&priv->tx_spinlock_, irq_flags);
++            return NETDEV_TX_BUSY;
++        }
 +
-+typedef struct rx_frag_info {
-+      struct page *page;
-+    dma_addr_t      phys_adr;
-+    u16             length;
-+} rx_frag_info_t;
++        // Should keep a record of the skb that we haven't been able to queue
++        // for transmission and queue it as soon as a descriptor becomes free
++        priv->tx_pending_skb = skb;
++        priv->tx_pending_fragment_count = fragment_count;
 +
-+/**
-+ * Fill a RX descriptor and pass ownership to DMA engine
-+ */
-+extern int set_rx_descriptor(
-+    gmac_priv_t    *priv,
-+    rx_frag_info_t *frag_info);
++        // Copy the fragment info to the allocated storage
++        memcpy(priv->tx_pending_fragments, fragments, sizeof(tx_frag_info_t) * fragment_count);
 +
-+/**
-+ * Extract data from the next available descriptor with which the GMAC DMA
-+ * controller has finished.
-+ * The caller indicates via the 'first_last' argument whether the first
-+ * descriptor contributing to a packet is expected. The 'first_last' argument
-+ * will be returned set to indicate whether the descriptor was the last
-+ * contributing to a packet.
-+ * If the 'status' argument is non-null it will have the status from the
-+ * descriptor or'ed into it, thus enabling the compound status for all
-+ * descriptors contributing to a packet to be built up
-+ */
-+extern int get_rx_descriptor(
-+    gmac_priv_t    *priv,
-+    int            *last,
-+    u32            *status,
-+    rx_frag_info_t *frag_info);
++        // Stop further calls to hard_start_xmit() until some descriptors are
++        // freed up by already queued TX packets being completed
++        netif_stop_queue(dev);
++    } else {
++        // Record start of transmission, so timeouts will work once they're
++        // implemented
++        dev->trans_start = jiffies;
 +
-+/**
-+ * Fill in descriptors describing all fragments in a single Tx packet and pass
-+ * ownership to the GMAC. The 'frag_info' argument points to an array describing
-+ * each buffer that is to contribute to the transmitted packet. The 'frag_count'
-+ * argument gives the number of elements in that array
-+ */
-+extern int set_tx_descriptor(
-+    gmac_priv_t    *priv,
-+    struct sk_buff *skb,
-+    tx_frag_info_t *frag_info,
-+    int             frag_count,
-+    int             use_hw_csum);
++        // Poke the transmitter to look for available TX descriptors, as we have
++        // just added one, in case it had previously found there were no more
++        // pending transmission
++        dma_reg_write(priv, DMA_TX_POLL_REG, 0);
++    }
 +
-+/**
-+ * Extract information about the TX packet transmitted the longest time ago.
-+ * If the 'status' argument is non-null it will have the status from the
-+ * descriptor or'ed into it.
-+ */
-+extern int get_tx_descriptor(
-+    gmac_priv_t     *priv,
-+    struct sk_buff **skb,
-+    u32             *status,
-+    tx_frag_info_t  *frag_info,
-+    int             *buffer_owned); 
++    spin_unlock_irqrestore(&priv->tx_spinlock_, irq_flags);
 +
-+/**
-+ * @param A u32 containing the status from a received frame's DMA descriptor
-+ * @return An int which is non-zero if a valid received frame has no error
-+ *         condititions flagged
-+ */
-+static inline int is_rx_valid(u32 status)
-+{
-+    return !(status & (1UL << RDES0_ES_BIT)) &&
-+           !(status & (1UL << RDES0_IPC_BIT));
++    return NETDEV_TX_OK;
 +}
++#endif // CONFIG_LEON_COPRO && CONFIG_LEON_OFFLOAD_TX
 +
-+static inline int is_rx_dribbling(u32 status)
++static struct net_device_stats *get_stats(struct net_device *dev)
 +{
-+    return status & (1UL << RDES0_DRE_BIT);
++    gmac_priv_t* priv = (gmac_priv_t*)netdev_priv(dev);
++    return &priv->stats;
 +}
 +
-+static inline u32 get_rx_length(u32 status)
++#ifdef CONFIG_NET_POLL_CONTROLLER
++/**
++ * Polling 'interrupt' - used by things like netconsole to send skbs without
++ * having to re-enable interrupts. It's not called while the interrupt routine
++ * is executing.
++ */
++static void netpoll(struct net_device *netdev)
 +{
-+    return (status >> RDES0_FL_BIT) & ((1UL << RX_DESC_STATUS_FL_NUM_BITS) - 1);
++    disable_irq(netdev->irq);
++    int_handler(netdev->irq, netdev, NULL);
++    enable_irq(netdev->irq);
 +}
++#endif // CONFIG_NET_POLL_CONTROLLER
 +
-+static inline int is_rx_collision_error(u32 status)
++static int probe(
++    struct net_device *netdev,
++    u32                vaddr,
++    u32                irq,
++    int                copro_a_irq,
++    int                copro_b_irq)
 +{
-+    return status & ((1UL << RDES0_OE_BIT) | (1UL << RDES0_LC_BIT));
-+}
++    int err = 0;
++    u32 version;
++    int i;
++    unsigned synopsis_version;
++    unsigned vendor_version;
++    gmac_priv_t* priv = netdev_priv(netdev);
++      u32 reg_contents;
 +
-+static inline int is_rx_crc_error(u32 status)
-+{
-+    return status & (1UL << RDES0_CE_BIT);
-+}
++    // Ensure the MAC block is properly reset
++    writel(1UL << SYS_CTRL_RSTEN_MAC_BIT, SYS_CTRL_RSTEN_SET_CTRL);
++    writel(1UL << SYS_CTRL_RSTEN_MAC_BIT, SYS_CTRL_RSTEN_CLR_CTRL);
 +
-+static inline int is_rx_frame_error(u32 status)
-+{
-+    return status & (1UL << RDES0_DE_BIT);
-+}
++    // Enable the clock to the MAC block
++    writel(1UL << SYS_CTRL_CKEN_MAC_BIT, SYS_CTRL_CKEN_SET_CTRL);
 +
-+static inline int is_rx_length_error(u32 status)
-+{
-+    return status & (1UL << RDES0_LE_BIT);
-+}
++    // Ensure reset and clock operations are complete
++    wmb();
 +
-+static inline int is_rx_csum_error(u32 status)
-+{
-+    return (status & (1UL << RDES0_IPC_BIT))
-+#ifndef CONFIG_HIPOX_VERSION_0X800
-+           || (status & (1UL << RDES0_PCE_BIT))
-+#endif // !CONFIG_HIPOX_VERSION_0X800
-+           ;
-+}
++    // Ensure all of the device private data are zero, so we can clean up in
++    // the event of a later failure to initialise all fields
++    priv = (gmac_priv_t*)netdev_priv(netdev);
++    memset(priv, 0, sizeof(gmac_priv_t));
 +
-+static inline int is_rx_long_frame(u32 status)
-+{
-+    return status & (1UL << RDES0_VLAN_BIT);
-+}
++    // No debug messages allowed
++    priv->msg_level = 0UL;
 +
-+static inline int is_tx_valid(u32 status)
-+{
-+    return !(status & (1UL << TDES0_ES_BIT));
-+}
++    // Initialise the ISR/hard_start_xmit() lock
++    spin_lock_init(&priv->tx_spinlock_);
++    
++    // Initialise the PHY access lock
++    spin_lock_init(&priv->phy_lock);
++
++    // Set hardware device base addresses
++    priv->macBase = vaddr + MAC_BASE_OFFSET;
++    priv->dmaBase = vaddr + DMA_BASE_OFFSET;
++
++    // Initialise IRQ ownership to not owned
++    priv->have_irq = 0;
++
++    // Lock protecting access to CoPro command queue functions or direct access
++    // to the GMAC interrupt enable register if CoPro is not in use
++    spin_lock_init(&priv->cmd_que_lock_);
 +
-+static inline int is_tx_collision_error(u32 status)
-+{
-+    return (status & (((1UL << TDES0_CC_NUM_BITS) - 1) << TDES0_CC_BIT)) >> TDES0_CC_BIT;
-+}
++#ifdef CONFIG_LEON_COPRO
++    sema_init(&copro_stop_semaphore, 0);
++    sema_init(&copro_start_semaphore, 0);
++    sema_init(&copro_int_clr_semaphore, 0);
++    sema_init(&copro_update_semaphore, 0);
++    sema_init(&copro_rx_enable_semaphore, 0);
++    priv->copro_a_irq_alloced_ = 0;
++    priv->copro_b_irq_alloced_ = 0;
++    sema_init(&priv->copro_stop_complete_semaphore_, 0);
++    INIT_LIST_HEAD(&priv->copro_tx_skb_list_);
++    priv->copro_tx_skb_list_count_ = 0;
++#endif // CONFIG_LEON_COPRO
 +
-+static inline int is_tx_aborted(u32 status)
-+{
-+    return status & ((1UL << TDES0_LC_BIT) | (1UL << TDES0_EC_BIT));
-+}
++    init_timer(&priv->watchdog_timer);
++    priv->watchdog_timer.function = &watchdog_timer_action;
++    priv->watchdog_timer.data = (unsigned long)priv;
 +
-+static inline int is_tx_carrier_error(u32 status)
-+{
-+    return status & ((1UL << TDES0_LOC_BIT) | (1UL << TDES0_NC_BIT));
-+}
++    // Set pointer to device in private data
++    priv->netdev = netdev;
 +
-+static inline u16 max_descriptor_length(void) {
-+      static const int GMAC_MAX_DESC_LEN = 2047;
++    /** Do something here to detect the present or otherwise of the MAC
++     *  Read the version register as a first test */
++    version = mac_reg_read(priv, MAC_VERSION_REG);
++    synopsis_version = version & 0xff;
++    vendor_version   = (version >> 8) & 0xff;
 +
-+      return GMAC_MAX_DESC_LEN;
-+}
-+#endif  //  #if !defined(__GMAC_DESC_H__)
++    /** Assume device is at the adr and irq specified until have probing working */
++    netdev->base_addr  = vaddr;
++    netdev->irq        = irq;
++#ifdef CONFIG_LEON_COPRO
++    priv->copro_a_irq_ = copro_a_irq;
++    priv->copro_b_irq_ = copro_b_irq;
++#endif // CONFIG_LEON_COPRO
 +
-diff -Nurd linux-2.6.24/arch/arm/mach-hipox/gmac_ethtool.c linux-2.6.24-oxe810/arch/arm/mach-hipox/gmac_ethtool.c
---- linux-2.6.24/arch/arm/mach-hipox/gmac_ethtool.c    1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mach-hipox/gmac_ethtool.c     2008-06-11 17:47:55.000000000 +0200
-@@ -0,0 +1,275 @@
-+/*
-+ * linux/arch/arm/mach-hipox/gmac_ethtool.c
-+ *
-+ * Copyright (C) 2005 Oxford Semiconductor Ltd
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+ 
-+#include <asm/types.h>
-+#include <linux/errno.h>
-+#include <linux/ethtool.h>
-+#include <linux/netdevice.h>
-+#include <asm/io.h>
-+#include <asm/arch/leon.h>
++#ifdef CONFIG_LEON_COPRO
++    // Allocate the CoPro A IRQ
++    err = request_irq(priv->copro_a_irq_, &copro_sema_intr, 0, "SEMA", netdev);
++    if (err) {
++        DBG(1, KERN_ERR "probe() %s: Failed to allocate CoPro irq A (%d)\n", netdev->name, priv->copro_a_irq_);
++        goto probe_err_out;
++    }
++    // Release the CoPro A IRQ again, as open()/stop() should manage IRQ ownership
++    free_irq(priv->copro_a_irq_, netdev);
 +
-+//#define GMAC_DEBUG
-+#undef GMAC_DEBUG
++    // Allocate the CoPro B IRQ
++    err = request_irq(priv->copro_b_irq_, &copro_semb_intr, 0, "SEMB", netdev);
++    if (err) {
++        DBG(1, KERN_ERR "probe() %s: Failed to allocate CoPro irq B (%d)\n", netdev->name, priv->copro_b_irq_);
++        goto probe_err_out;
++    }
++    // Release the CoPro B IRQ again, as open()/stop() should manage IRQ ownership
++    free_irq(priv->copro_b_irq_, netdev);
++#else // CONFIG_LEON_COPRO
++    // Allocate the IRQ
++    err = request_irq(netdev->irq, &int_handler, 0, netdev->name, netdev);
++    if (err) {
++        DBG(1, KERN_ERR "probe() %s: Failed to allocate irq %d\n", netdev->name, netdev->irq);
++        goto probe_err_out;
++    }
 +
-+#include "gmac.h"
-+#include "gmac_desc.h"
++    // Release the IRQ again, as open()/stop() should manage IRQ ownership
++    free_irq(netdev->irq, netdev);
++#endif // CONFIG_LEON_COPRO
 +
-+static int get_settings(struct net_device* dev, struct ethtool_cmd* cmd)
-+{
-+    gmac_priv_t* priv = (gmac_priv_t*)netdev_priv(dev);
-+    unsigned long irq_flags;
-+    int status;
++    // Initialise the ethernet device with std. contents
++    ether_setup(netdev);
 +
-+    spin_lock_irqsave(&priv->phy_lock, irq_flags);
-+    status = mii_ethtool_gset(&priv->mii, cmd);
-+    spin_unlock_irqrestore(&priv->phy_lock, irq_flags);
++    // Tell the kernel of our MAC address
++      for (i = 0; i < netdev->addr_len; i++) {
++              netdev->dev_addr[i] = (unsigned char)mac_adr[i];
++      }
 +
-+    return status;
-+}
++    // Setup operations pointers
++    netdev->open               = &open;
++    netdev->hard_start_xmit    = &hard_start_xmit;
++    netdev->stop               = &stop;
++    netdev->get_stats          = &get_stats;
++    netdev->change_mtu         = &change_mtu;
++#ifdef CONFIG_NET_POLL_CONTROLLER
++    netdev->poll_controller    = &netpoll;
++#endif // CONFIG_NET_POLL_CONTROLLER
++    netdev->set_mac_address    = &set_mac_address;
++    netdev->set_multicast_list = &set_multicast_list;
 +
-+static int set_settings(struct net_device* dev, struct ethtool_cmd* cmd)
-+{
-+    gmac_priv_t* priv = (gmac_priv_t*)netdev_priv(dev);
-+    unsigned long irq_flags;
-+    int status;
++      // Initialise NAPI support
++      netif_napi_add(netdev, &priv->napi_struct, &poll, NAPI_POLL_WEIGHT);
 +
-+    spin_lock_irqsave(&priv->phy_lock, irq_flags);
-+    status = mii_ethtool_sset(&priv->mii, cmd);
-+    spin_unlock_irqrestore(&priv->phy_lock, irq_flags);
++    set_ethtool_ops(netdev);
 +
-+    return status;
-+}
++    if (debug) {
++      netdev->flags |= IFF_DEBUG;
++    }
 +
-+static void get_drvinfo(struct net_device* dev, struct ethtool_drvinfo* drvinfo)
-+{
-+    strncpy(drvinfo->driver,     "GMAC", 32);
-+    strncpy(drvinfo->version,    "1.0", 32);
-+    strncpy(drvinfo->fw_version, "1.0", 32);    // Version of CoPro s/w
-+    strncpy(drvinfo->bus_info,   "AMBA", 32);
-+}
++#if defined(CONFIG_LEON_COPRO) && defined(CONFIG_LEON_OFFLOAD_TSO)
++    // Do TX H/W checksum and SG list processing
++    netdev->features |= NETIF_F_HW_CSUM;
++    netdev->features |= NETIF_F_SG;
 +
-+static int nway_reset(struct net_device* dev)
-+{
-+    gmac_priv_t* priv = (gmac_priv_t*)netdev_priv(dev);
-+    unsigned long irq_flags;
-+    int status;
++    // Do hardware TCP/IP Segmentation Offload
++    netdev->features |= NETIF_F_TSO;
++#elif !defined(CONFIG_LEON_COPRO) && !defined(CONFIG_HIPOX_VERSION_0X800)
++    // Do TX H/W checksum and SG list processing
++    netdev->features |= NETIF_F_HW_CSUM;
++    netdev->features |= NETIF_F_SG;
++#endif // USE_TX_CSUM
 +
-+    spin_lock_irqsave(&priv->phy_lock, irq_flags);
-+    status = mii_nway_restart(&priv->mii);
-+    spin_unlock_irqrestore(&priv->phy_lock, irq_flags);
++    // We take care of our own TX locking
++    netdev->features |= NETIF_F_LLTX;
 +
-+    return status;
-+}
++    // Initialise PHY support
++    priv->mii.phy_id_mask   = 0x1f;
++    priv->mii.reg_num_mask  = 0x1f;
++    priv->mii.force_media   = 0;
++    priv->mii.full_duplex   = 1;
++    priv->mii.using_100     = 0;
++    priv->mii.using_1000    = 1;
++      priv->mii.using_pause   = 1;
++    priv->mii.dev           = netdev;
++    priv->mii.mdio_read     = phy_read;
++    priv->mii.mdio_write    = phy_write;
 +
-+static u32 get_msglevel(struct net_device* dev)
-+{
-+    return ((gmac_priv_t*)netdev_priv(dev))->msg_level;
-+}
++    priv->gmii_csr_clk_range = 5;   // Slowest for now
 +
-+static void set_msglevel(struct net_device* dev, u32 data)
-+{
-+    ((gmac_priv_t*)netdev_priv(dev))->msg_level = data;
-+}
++    // Use simple mux for 25/125 Mhz clock switching and
++    // enable GMII_GTXCLK to follow GMII_REFCLK - required for gigabit PHY
++      reg_contents = readl(SYS_CTRL_GMAC_CTRL);
++      reg_contents |= ((1UL << SYS_CTRL_GMAC_SIMPLE_MAX) |
++                                        (1UL << SYS_CTRL_GMAC_CKEN_GTX));
++    writel(reg_contents, SYS_CTRL_GMAC_CTRL);
 +
-+static u32 get_rx_csum(struct net_device* dev)
-+{
-+#ifdef USE_RX_CSUM
-+      return 1;
-+#else
-+      return 0;
-+#endif
-+}
++    // Remember whether auto-negotiation is allowed
++#ifdef ALLOW_AUTONEG
++    priv->ethtool_cmd.autoneg = 1;
++      priv->ethtool_pauseparam.autoneg = 1;
++#else // ALLOW_AUTONEG
++    priv->ethtool_cmd.autoneg = 0;
++      priv->ethtool_pauseparam.autoneg = 0;
++#endif // ALLOW_AUTONEG
 +
-+static int set_rx_csum(struct net_device* dev, u32 data)
-+{
-+    return 0;
-+}
++    // Set up PHY mode for when auto-negotiation is not allowed
++    priv->ethtool_cmd.speed = SPEED_1000;
++    priv->ethtool_cmd.duplex = DUPLEX_FULL;
++    priv->ethtool_cmd.port = PORT_MII;
++    priv->ethtool_cmd.transceiver = XCVR_INTERNAL;
 +
-+static int get_regs_len(struct net_device* dev)
-+{
-+    return 0;
-+}
++#ifndef CONFIG_HIPOX_VERSION_0X800
++      // We can support both reception and generation of pause frames
++      priv->ethtool_pauseparam.rx_pause = 1;
++      priv->ethtool_pauseparam.tx_pause = 1;
++#endif // !CONFIG_HIPOX_VERSION_0X800
 +
-+static void get_regs(struct net_device* dev, struct ethtool_regs* regs, void *p)
-+{
-+    gmac_priv_t   *priv = (gmac_priv_t*)netdev_priv(dev);
-+    unsigned long  irq_state;
-+      u32            status;
++    // Initialise the set of features we would like to advertise as being
++      // available for negotiation
++    priv->ethtool_cmd.advertising = (ADVERTISED_10baseT_Half |
++                                     ADVERTISED_10baseT_Full |
++                                     ADVERTISED_100baseT_Half |
++                                     ADVERTISED_100baseT_Full |
++#if !defined(CONFIG_HIPOX_VERSION_0X800) || defined(ALLOW_OX800_1000M)
++                                     ADVERTISED_1000baseT_Half |
++                                     ADVERTISED_1000baseT_Full |
++                                                                        ADVERTISED_Pause |
++                                                                        ADVERTISED_Asym_Pause |
++#endif
++                                     ADVERTISED_Autoneg |
++                                     ADVERTISED_MII);
 +
-+    printk("RX ring info:\n");
-+    printk("  num_descriptors     = %d\n", priv->rx_gmac_desc_list_info.num_descriptors);
-+    printk("  empty_count         = %d\n", priv->rx_gmac_desc_list_info.empty_count);
-+    printk("  full_count          = %d\n", priv->rx_gmac_desc_list_info.full_count);
-+    printk("  r_index             = %d\n", priv->rx_gmac_desc_list_info.r_index);
-+    printk("  w_index             = %d\n", priv->rx_gmac_desc_list_info.w_index);
-+    printk("  available_for_write = %d\n", available_for_write(&priv->rx_gmac_desc_list_info));
-+    printk("  available_for_read    %s\n", rx_available_for_read(&priv->rx_gmac_desc_list_info, 0) ? "yes" :"no");
++    // Attempt to locate the PHY
++    phy_detect(netdev);
++    priv->ethtool_cmd.phy_address = priv->mii.phy_id;
 +
-+    spin_lock_irqsave(&priv->tx_spinlock_, irq_state);
-+    printk("TX ring info:\n");
-+    printk("  num_descriptors     = %d\n", priv->tx_gmac_desc_list_info.num_descriptors);
-+    printk("  empty_count         = %d\n", priv->tx_gmac_desc_list_info.empty_count);
-+    printk("  full_count          = %d\n", priv->tx_gmac_desc_list_info.full_count);
-+    printk("  r_index             = %d\n", priv->tx_gmac_desc_list_info.r_index);
-+    printk("  w_index             = %d\n", priv->tx_gmac_desc_list_info.w_index);
-+    printk("  available_for_write = %d\n", available_for_write(&priv->tx_gmac_desc_list_info));
-+    printk("  available_for_read    %s\n", tx_available_for_read(&priv->tx_gmac_desc_list_info, &status) ? "yes" : "no");
-+    spin_unlock_irqrestore(&priv->tx_spinlock_, irq_state);
-+}
++    // Did we find a PHY?
++      if (priv->phy_type == PHY_TYPE_NONE) {
++              printk(KERN_WARNING "%s: No PHY found\n", netdev->name);
++              err = ENXIO;
++              goto probe_err_out;
++    }
 +
-+static void get_wol(struct net_device* dev, struct ethtool_wolinfo* wol_info)
-+{
-+}
++      // Setup the PHY
++      initialise_phy(priv);
 +
-+static int set_wol(struct net_device* dev, struct ethtool_wolinfo* wol_info)
-+{
-+    return -EINVAL;
-+}
++      // Find out what modes the PHY supports
++      priv->ethtool_cmd.supported = get_phy_capabilies(priv);
++#if defined(CONFIG_HIPOX_VERSION_0X800) && !defined(ALLOW_OX800_1000M)
++      // OX800 has broken 1000M support in the MAC
++      priv->ethtool_cmd.supported &= ~(SUPPORTED_1000baseT_Full | SUPPORTED_1000baseT_Half);
++#endif
 +
-+static int get_coalesce(struct net_device* dev, struct ethtool_coalesce *ethtool_coalesce)
-+{
-+#ifdef CONFIG_LEON_COPRO
-+    gmac_priv_t* priv = (gmac_priv_t*)netdev_priv(dev);
++    // Register the device with the network intrastructure
++    err = register_netdev(netdev);
++    if (err) {
++        DBG(1, KERN_ERR "probe() %s: Failed to register device\n", netdev->name);
++        goto probe_err_out;
++    }
 +
-+    if (priv->copro_params_.rx_mitigation_) {
-+        ethtool_coalesce->rx_max_coalesced_frames = priv->copro_params_.rx_mitigation_frames_;
-+        ethtool_coalesce->rx_coalesce_usecs       = priv->copro_params_.rx_mitigation_usec_;
-+printk("get_coalesce() %u packets, %u usec\n", ethtool_coalesce->rx_max_coalesced_frames, ethtool_coalesce->rx_coalesce_usecs);
++    // Record details about the hardware we found
++    printk(KERN_NOTICE "%s: GMAC ver = %u, vendor ver = %u at 0x%lx, IRQ %d\n", netdev->name, synopsis_version, vendor_version, netdev->base_addr, netdev->irq);
++#ifndef ARMULATING
++    printk(KERN_NOTICE "%s: Found PHY at address %u, type 0x%08x -> %s\n", priv->netdev->name, priv->phy_addr, priv->phy_type, (priv->ethtool_cmd.supported & SUPPORTED_1000baseT_Full) ? "10/100/1000" : "10/100");
++#endif // !ARMULATING
++    printk(KERN_NOTICE "%s: Ethernet addr: ", priv->netdev->name);
++    for (i = 0; i < 5; i++) {
++        printk("%02x:", netdev->dev_addr[i]);
 +    }
-+#endif // CONFIG_LEON_COPRO
-+   return 0;
-+}
++    printk("%02x\n", netdev->dev_addr[5]);
 +
-+static int set_coalesce(struct net_device* dev, struct ethtool_coalesce *ethtool_coalesce)
-+{
 +#ifdef CONFIG_LEON_COPRO
-+    gmac_priv_t* priv = (gmac_priv_t*)netdev_priv(dev);
++    // Define sizes of queues for communicating with the CoPro
++    priv->copro_cmd_que_num_entries_ = COPRO_CMD_QUEUE_NUM_ENTRIES;
++    priv->copro_tx_que_num_entries_ = COPRO_TX_QUEUE_NUM_ENTRIES;
++#endif // CONFIG_LEON_COPRO 
 +
-+    if (priv->copro_params_.rx_mitigation_) {
-+printk("set_coalesce() %u packets, %u usec\n", ethtool_coalesce->rx_max_coalesced_frames, ethtool_coalesce->rx_coalesce_usecs);
-+        priv->copro_params_.rx_mitigation_frames_ = ethtool_coalesce->rx_max_coalesced_frames;
-+        priv->copro_params_.rx_mitigation_usec_   = ethtool_coalesce->rx_coalesce_usecs;
++      // Initialise sysfs for link state reporting
++      err = gmac_link_state_init_sysfs(priv);
++      if (err) {
++        DBG(1, KERN_ERR "probe() %s: Failed to initialise sysfs support\n", netdev->name);
++        goto probe_err_out;
++      }
 +
-+        // Only attempt to write to uncached/unbuffered shared parameter storage
-+        // if CoPro is started and thus storage has been allocated
-+        if (priv->shared_copro_params_) {
-+            // Fill the CoPro parameter block
-+            memcpy(priv->shared_copro_params_, &priv->copro_params_, sizeof(copro_params_t));
-+        }
++      // Initialise the work queue entry to be used to issue hotplug events to userspace
++      INIT_WORK(&priv->link_state_change_work, work_handler);
 +
-+        // Make sure the CoPro parameter block updates have made it to memory (which
-+        // is uncached/unbuffered, so just compiler issues to overcome)
-+        wmb();
++    return 0;
 +
-+        spin_lock(&priv->cmd_que_lock_);
-+        cmd_que_queue_cmd(&priv->cmd_queue_, GMAC_CMD_UPDATE_PARAMS, 0, 0);
-+        spin_unlock(&priv->cmd_que_lock_);
++probe_err_out:
++#ifdef CONFIG_LEON_COPRO 
++    shutdown_copro();
 +
-+        // Interrupt the CoPro so it sees the new command
-+        writel(1UL << COPRO_SEM_INT_CMD, SYS_CTRL_SEMA_SET_CTRL);
++    if (priv->shared_copro_params_) {
++        // Free the DMA coherent parameter space
++        dma_free_coherent(0, sizeof(copro_params_t), priv->shared_copro_params_, priv->shared_copro_params_pa_);
++        priv->shared_copro_params_ = 0;
 +    }
-+#endif // CONFIG_LEON_COPRO
++#endif // CONFIG_LEON_COPRO 
 +
-+    return 0;
-+}
++    // Disable the clock to the MAC block
++    writel(1UL << SYS_CTRL_CKEN_MAC_BIT, SYS_CTRL_CKEN_CLR_CTRL);
 +
-+static void get_ringparam(struct net_device* dev, struct ethtool_ringparam *ethtool_ringparam)
-+{
++    return err;
 +}
 +
-+static int set_ringparam(struct net_device* dev, struct ethtool_ringparam *ethtool_ringparam)
-+{
-+    return -EINVAL;
-+}
++static int gmac_found_count = 0;
++static struct net_device* gmac_netdev[MAX_GMAC_UNITS];
 +
-+static void get_pauseparam(struct net_device* dev, struct ethtool_pauseparam* ethtool_pauseparam)
++/**
++ * External entry point to the driver, called from Space.c to detect a card
++ */
++struct net_device* __init synopsys_gmac_probe(int unit)
 +{
-+}
++    int err = 0;
++    struct net_device *netdev = alloc_etherdev(sizeof(gmac_priv_t));
 +
-+static int set_pauseparam(struct net_device* dev, struct ethtool_pauseparam* ethtool_pauseparam)
-+{
-+    return -EINVAL;
-+}
++    printk(KERN_NOTICE "Probing for Synopsis GMAC, unit %d\n", unit);
 +
-+static int self_test_count(struct net_device* dev)
-+{
-+    return -EINVAL;
-+}
++    // Will allocate private data later, as may want descriptors etc in special memory
++    if (!netdev) {
++        printk(KERN_WARNING "synopsys_gmac_probe() failed to alloc device\n");
++        err = -ENODEV;
++    } else {
++        if (unit >= 0) {
++            sprintf(netdev->name, "eth%d", unit);
 +
-+static void self_test(struct net_device* dev, struct ethtool_test* ethtool_test, u64 *data)
-+{
-+}
++            netdev_boot_setup_check(netdev);
 +
-+static void get_strings(struct net_device* dev, u32 stringset, u8 *data)
-+{
-+}
++            if (gmac_found_count >= MAX_GMAC_UNITS) {
++                err = -ENODEV;
++            } else {
++                err = probe(netdev, MAC_BASE, MAC_INTERRUPT, SEM_A_INTERRUPT, SEM_B_INTERRUPT);
++                if (err) {
++                    printk(KERN_WARNING "synopsys_gmac_probe() Probing failed for %s\n", netdev->name);
++                } else {
++                    ++gmac_found_count;
++                }
++            }
++        }
 +
-+static int phys_id(struct net_device* dev, u32 data)
-+{
-+    return -EINVAL;
-+}
++        if (err) {
++            netdev->reg_state = NETREG_UNREGISTERED;
++            free_netdev(netdev);
++        } else {
++                      gmac_netdev[unit] = netdev;
++              }
++    }
 +
-+static int get_stats_count(struct net_device* dev)
-+{
-+    return -EINVAL;
++    return ERR_PTR(err);
 +}
 +
-+static void get_ethtool_stats(struct net_device* dev, struct ethtool_stats* ethtool_stats, u64 *data)
++static int __init gmac_module_init(void)
 +{
++      return (int)synopsys_gmac_probe(0);
 +}
++module_init(gmac_module_init);
 +
-+static struct ethtool_ops ethtool_ops = {
-+    .get_settings      = get_settings,
-+    .set_settings      = set_settings,
-+    .get_drvinfo       = get_drvinfo,
-+    .get_regs_len      = get_regs_len,
-+    .get_regs          = get_regs,
-+    .get_wol           = get_wol,
-+    .set_wol           = set_wol,
-+    .get_msglevel      = get_msglevel,
-+    .set_msglevel      = set_msglevel,
-+    .nway_reset        = nway_reset,
-+    .get_link          = ethtool_op_get_link,
-+    .get_coalesce      = get_coalesce,
-+    .set_coalesce      = set_coalesce,
-+    .get_ringparam     = get_ringparam,
-+    .set_ringparam     = set_ringparam,
-+    .get_pauseparam    = get_pauseparam,
-+    .set_pauseparam    = set_pauseparam,
-+    .get_rx_csum       = get_rx_csum,
-+    .set_rx_csum       = set_rx_csum,
-+    .get_tx_csum       = ethtool_op_get_tx_csum,
-+    .set_tx_csum       = ethtool_op_set_tx_csum,
-+    .get_sg            = ethtool_op_get_sg,
-+    .set_sg            = ethtool_op_set_sg,
-+    .get_tso           = ethtool_op_get_tso,
-+    .set_tso           = ethtool_op_set_tso,
-+    .self_test_count   = self_test_count,
-+    .self_test         = self_test,
-+    .get_strings       = get_strings,
-+    .phys_id           = phys_id,
-+    .get_stats_count   = get_stats_count,
-+    .get_ethtool_stats = get_ethtool_stats
-+};
-+
-+void set_ethtool_ops(struct net_device *netdev)
++static void __exit gmac_module_cleanup(void)
 +{
-+    SET_ETHTOOL_OPS(netdev, &ethtool_ops);
++      int i;
++      for (i=0; i < gmac_found_count; i++) {
++              stop(gmac_netdev[i]);
++              gmac_netdev[i]->reg_state = NETREG_UNREGISTERED;
++              free_netdev(gmac_netdev[i]);
++      }
 +}
-diff -Nurd linux-2.6.24/arch/arm/mach-hipox/gmac_ethtool.h linux-2.6.24-oxe810/arch/arm/mach-hipox/gmac_ethtool.h
---- linux-2.6.24/arch/arm/mach-hipox/gmac_ethtool.h    1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mach-hipox/gmac_ethtool.h     2008-06-11 17:47:55.000000000 +0200
-@@ -0,0 +1,26 @@
-+/*
-+ * linux/arch/arm/mach-hipox/gmac_ethtool.h
-+ *
-+ * Copyright (C) 2005 Oxford Semiconductor Ltd
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+#if !defined(__GMAC_ETHTOOL_H__)
-+#define __GMAC_ETHTOOL_H__
-+
-+extern void set_ethtool_ops(struct net_device *netdev);
-+
-+#endif        //  #if !defined(__GMAC_ETHTOOL_H__)
++module_exit(gmac_module_cleanup);
 +
-diff -Nurd linux-2.6.24/arch/arm/mach-hipox/gmac_offload.c linux-2.6.24-oxe810/arch/arm/mach-hipox/gmac_offload.c
---- linux-2.6.24/arch/arm/mach-hipox/gmac_offload.c    1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mach-hipox/gmac_offload.c     2008-06-11 17:47:55.000000000 +0200
+diff -Nurd linux-2.6.24.4/arch/arm/mach-hipox/gmac_offload.c linux-2.6.24/arch/arm/mach-hipox/gmac_offload.c
+--- linux-2.6.24.4/arch/arm/mach-hipox/gmac_offload.c  1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/mach-hipox/gmac_offload.c    2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,223 @@
 +/*
 + * linux/arch/arm/mach-hipox/gmac-offload.c
@@ -18210,9 +17282,9 @@ diff -Nurd linux-2.6.24/arch/arm/mach-hipox/gmac_offload.c linux-2.6.24-oxe810/a
 +}
 +#endif // #ifdef CONFIG_LEON_COPRO
 +
-diff -Nurd linux-2.6.24/arch/arm/mach-hipox/gmac_offload.h linux-2.6.24-oxe810/arch/arm/mach-hipox/gmac_offload.h
---- linux-2.6.24/arch/arm/mach-hipox/gmac_offload.h    1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mach-hipox/gmac_offload.h     2008-06-11 17:47:55.000000000 +0200
+diff -Nurd linux-2.6.24.4/arch/arm/mach-hipox/gmac_offload.h linux-2.6.24/arch/arm/mach-hipox/gmac_offload.h
+--- linux-2.6.24.4/arch/arm/mach-hipox/gmac_offload.h  1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/mach-hipox/gmac_offload.h    2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,163 @@
 +/*
 + * linux/arch/arm/mach-hipox/gmac-offload.h
@@ -18377,9 +17449,9 @@ diff -Nurd linux-2.6.24/arch/arm/mach-hipox/gmac_offload.h linux-2.6.24-oxe810/a
 +
 +#endif        //  #if !defined(__GMAC_OFFLOAD_H__)
 +#endif // CONFIG_LEON_COPRO
-diff -Nurd linux-2.6.24/arch/arm/mach-hipox/gmac_phy.c linux-2.6.24-oxe810/arch/arm/mach-hipox/gmac_phy.c
---- linux-2.6.24/arch/arm/mach-hipox/gmac_phy.c        1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mach-hipox/gmac_phy.c 2008-06-11 17:47:55.000000000 +0200
+diff -Nurd linux-2.6.24.4/arch/arm/mach-hipox/gmac_phy.c linux-2.6.24/arch/arm/mach-hipox/gmac_phy.c
+--- linux-2.6.24.4/arch/arm/mach-hipox/gmac_phy.c      1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/mach-hipox/gmac_phy.c        2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,318 @@
 +/*
 + * linux/arch/arm/mach-hipox/gmac_phy.c
@@ -18699,9 +17771,9 @@ diff -Nurd linux-2.6.24/arch/arm/mach-hipox/gmac_phy.c linux-2.6.24-oxe810/arch/
 +
 +      return features;
 +}
-diff -Nurd linux-2.6.24/arch/arm/mach-hipox/gmac_phy.h linux-2.6.24-oxe810/arch/arm/mach-hipox/gmac_phy.h
---- linux-2.6.24/arch/arm/mach-hipox/gmac_phy.h        1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mach-hipox/gmac_phy.h 2008-06-11 17:47:55.000000000 +0200
+diff -Nurd linux-2.6.24.4/arch/arm/mach-hipox/gmac_phy.h linux-2.6.24/arch/arm/mach-hipox/gmac_phy.h
+--- linux-2.6.24.4/arch/arm/mach-hipox/gmac_phy.h      1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/mach-hipox/gmac_phy.h        2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,78 @@
 +/*
 + * linux/arch/arm/mach-hipox/gmac_phy.h
@@ -18781,9 +17853,9 @@ diff -Nurd linux-2.6.24/arch/arm/mach-hipox/gmac_phy.h linux-2.6.24-oxe810/arch/
 +extern u32 get_phy_capabilies(gmac_priv_t* priv);
 +#endif        //  #if !defined(__GMAC_PHY_H__)
 +
-diff -Nurd linux-2.6.24/arch/arm/mach-hipox/gmac_reg.h linux-2.6.24-oxe810/arch/arm/mach-hipox/gmac_reg.h
---- linux-2.6.24/arch/arm/mach-hipox/gmac_reg.h        1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mach-hipox/gmac_reg.h 2008-06-11 17:47:55.000000000 +0200
+diff -Nurd linux-2.6.24.4/arch/arm/mach-hipox/gmac_reg.h linux-2.6.24/arch/arm/mach-hipox/gmac_reg.h
+--- linux-2.6.24.4/arch/arm/mach-hipox/gmac_reg.h      1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/mach-hipox/gmac_reg.h        2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,508 @@
 +/*
 + * linux/arch/arm/mach-hipox/gmac_reg.h
@@ -19293,9 +18365,9 @@ diff -Nurd linux-2.6.24/arch/arm/mach-hipox/gmac_reg.h linux-2.6.24-oxe810/arch/
 +
 +#endif        //  #if !defined(__GMAC_REG_H__)
 +
-diff -Nurd linux-2.6.24/arch/arm/mach-hipox/gpioTest.c linux-2.6.24-oxe810/arch/arm/mach-hipox/gpioTest.c
---- linux-2.6.24/arch/arm/mach-hipox/gpioTest.c        1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mach-hipox/gpioTest.c 2008-06-11 17:47:55.000000000 +0200
+diff -Nurd linux-2.6.24.4/arch/arm/mach-hipox/gpioTest.c linux-2.6.24/arch/arm/mach-hipox/gpioTest.c
+--- linux-2.6.24.4/arch/arm/mach-hipox/gpioTest.c      1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/mach-hipox/gpioTest.c        2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,657 @@
 +#include <asm/io.h>
 +#include <asm/bitops.h>
@@ -19954,368 +19026,392 @@ diff -Nurd linux-2.6.24/arch/arm/mach-hipox/gpioTest.c linux-2.6.24-oxe810/arch/
 +
 +module_init(gpioTest_init);
 +module_exit(gpioTest_exit);
-diff -Nurd linux-2.6.24/arch/arm/mach-hipox/i2s.c linux-2.6.24-oxe810/arch/arm/mach-hipox/i2s.c
---- linux-2.6.24/arch/arm/mach-hipox/i2s.c     1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mach-hipox/i2s.c      2008-06-11 17:47:55.000000000 +0200
-@@ -0,0 +1,352 @@
-+/* 
-+ *  procfs3.c -  create a "file" in /proc, use the file_operation way
-+ *            to manage the file.
+diff -Nurd linux-2.6.24.4/arch/arm/mach-hipox/hipox-ahb-monitor.c linux-2.6.24/arch/arm/mach-hipox/hipox-ahb-monitor.c
+--- linux-2.6.24.4/arch/arm/mach-hipox/hipox-ahb-monitor.c     1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/mach-hipox/hipox-ahb-monitor.c       2010-01-14 14:01:15.000000000 +0100
+@@ -0,0 +1,374 @@
++/*
++ *  arch/arm/mach-hipox/hipox-ahb-monitor.c
++ *
++ *  Copyright (C) 2006 Oxford Semiconductor Ltd
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ *
 + */
-+ 
++
 +#include <linux/types.h>
++#include <linux/module.h>
 +#include <linux/errno.h>
++#include <linux/miscdevice.h>
++#include <linux/smp_lock.h>
++#include <linux/kernel.h>
++#include <linux/delay.h>
++#include <linux/sched.h>
++#include <linux/i2c.h>
++#include <linux/proc_fs.h>
++#include <linux/capability.h>
++#include <linux/slab.h>
 +#include <linux/init.h>
-+#include <linux/kernel.h>     /* We're doing kernel work */
-+#include <linux/module.h>     /* Specifically, a module */
-+#include <linux/proc_fs.h>    /* Necessary because we use proc fs */
-+#include <asm/uaccess.h>              /* for copy_*_user */
-+#include "asm/arch-hipox/i2s.h"
-+#include "asm/io.h"
++#include <linux/spinlock.h>
++#include <linux/smp_lock.h>
++#include <linux/wait.h>
++#include <linux/suspend.h>
++#include <linux/kthread.h>
++#include <linux/moduleparam.h>
 +
-+#define DRV_NAME              "i2s"
-+#define DRV_VERSION   "0.1"
-+#define PROC_ENTRY_FILENAME   "i2s"
-+#define PROCFS_MAX_SIZE       2048
++#include <asm/io.h>
++#include <asm/system.h>
++#include <asm/sections.h>
++#include <asm/uaccess.h>
++#include <asm/bitops.h>
 +
++#include <asm/hardware.h>
 +
 +
-+MODULE_AUTHOR("Chris Ford");
-+MODULE_DESCRIPTION("I2S Test module");
-+MODULE_LICENSE("GPL");
-+MODULE_VERSION(DRV_VERSION);
++/* usb test masks and offsets */
++#define TEST_MASK    0xF
++#define TEST_OFFSET  16
 +
-+/**
-+ * The buffer (2k) for this module
-+ *
-+ */
-+static char procfs_buffer[PROCFS_MAX_SIZE];
++#define MODULE_VERS "0.1"
++#define MODULE_NAME "hipox-test"
++MODULE_AUTHOR(                "John Larkworthy"                                       );
++MODULE_DESCRIPTION(   "Driver to access the test hardware in hipox units"     );
++MODULE_LICENSE(               "GPL"                                                   );
 +
-+/**
-+ * The size of the data hold in the buffer
-+ *
-+ */
-+static unsigned long procfs_buffer_size = 0;
 +
-+/**
-+ * The structure keeping information about the /proc file
-+ *
-+ */
-+static struct proc_dir_entry *Our_Proc_File;
++static struct proc_dir_entry *proc_dir_usb_test_read, *hipox_test_dir;
 +
 +
-+void RefreshI2SRegisters(void)
++static struct {
++      void * address;
++      char * name;
++      long unsigned low_add;
++      long unsigned high_add;
++      unsigned burst;
++      unsigned burst_mask;
++      unsigned hprot;
++      unsigned hprot_mask;
++      unsigned mode;
++} monitor[] =
++{
++      { (void *) 0x00000, "ARM_Data", 0, 0xFFFFFFFFl, 0, 0, 0, 0, 0 },
++      { (void *) 0x10000, "Arm_Inst", 0, 0xFFFFFFFFl, 0, 0, 0, 0, 0 },
++      { (void *) 0x20000, "DMA_A", 0, 0xFFFFFFFFl, 0, 0, 0, 0, 0 },
++      { (void *) 0x30000, "DMA_B", 0, 0xFFFFFFFFl, 0, 0, 0, 0, 0 },
++      { (void *) 0x40000, "CoPro", 0, 0xFFFFFFFFl, 0, 0, 0, 0, 0 },
++      { (void *) 0x50000, "USBHS", 0, 0xFFFFFFFFl, 0, 0, 0, 0, 0 },
++      { (void *) 0x60000, "GMAC", 0, 0xFFFFFFFFl, 0, 0, 0, 0, 0 },
++      { (void *) 0x70000, "PCI", 0, 0xFFFFFFFFl, 0, 0, 0, 0, 0 }
++};            
++#define NO_MONITORS (sizeof(monitor)/sizeof(monitor[0]))
++
++/* create proc filing system entries to accept configuration data */
++static int usb_test_write_entries(const char *name, write_proc_t *w, read_proc_t *r, int data)
++{
++      struct proc_dir_entry * entry = create_proc_entry(name, 0222, hipox_test_dir);
++      if (entry) {
++              entry->write_proc = w;
++              entry->read_proc =r;
++              entry->data = (void *)data;
++              entry->owner = THIS_MODULE;
++              return 0;
++      }
++      else
++      {
++              return -ENOMEM;
++      }
++}
++
++static int
++hipox_test_read(char *buf, char **start, off_t offset,
++                int count, int *eof, void *unused)
 +{
-+      int iLen = sprintf( procfs_buffer,  
-+              "DumpI2SRegisters----------------------------------\n"
-+              "                                                  \n"
-+              "     TX_CONTROL                = 0x%08x\n"
-+              "     TX_SETUP                  = 0x%08x\n"
-+              "     TX_SETUP1                 = 0x%08x\n"
-+              "     TX_STATUS                 = 0x%08x\n"
-+              "     RX_CONTROL                = 0x%08x\n"
-+              "     RX_SETUP                  = 0x%08x\n"
-+              "     RX_SETUP1                 = 0x%08x\n"
-+              "     RX_STATUS                 = 0x%08x\n"
-+              "     TX_DEBUG                  = 0x%08x\n"
-+              "     TX_DEBUG2                 = 0x%08x\n"
-+              "     TX_DEBUG3                 = 0x%08x\n"
-+              "     RX_DEBUG_                 = 0x%08x\n"
-+              "     RX_DEBUG2                 = 0x%08x\n"
-+              "     RX_DEBUG3                 = 0x%08x\n"
-+              "     TX_BUFFER_LEVEL           = 0x%08x\n"
-+              "     TX_BUFFER_INTERRUPT_LEVEL = 0x%08x\n"
-+              "     RX_BUFFER_LEVEL           = 0x%08x\n"
-+              "     RX_BUFFER_INTERRUPT_LEVEL = 0x%08x\n"
-+              "     RX_SPDIF_DEBUG            = 0x%08x\n"
-+              "     RX_SPDIF_DEBUG2           = 0x%08x\n",
-+              (u32) __raw_readl( TX_CONTROL                 ),
-+              (u32) __raw_readl( TX_SETUP                   ),
-+              (u32) __raw_readl( TX_SETUP1                  ),
-+              (u32) __raw_readl( TX_STATUS                  ),
-+              (u32) __raw_readl( RX_CONTROL                 ),
-+              (u32) __raw_readl( RX_SETUP                   ),
-+              (u32) __raw_readl( RX_SETUP1                  ),
-+              (u32) __raw_readl( RX_STATUS                  ),
-+              (u32) __raw_readl( TX_DEBUG                   ),
-+              (u32) __raw_readl( TX_DEBUG2                  ),
-+              (u32) __raw_readl( TX_DEBUG3                  ),
-+              (u32) __raw_readl( RX_DEBUG_                  ),
-+              (u32) __raw_readl( RX_DEBUG2                  ),
-+              (u32) __raw_readl( RX_DEBUG3                  ),
-+              (u32) __raw_readl( TX_BUFFER_LEVEL            ),
-+              (u32) __raw_readl( TX_BUFFER_INTERRUPT_LEVEL  ),
-+              (u32) __raw_readl( RX_BUFFER_LEVEL            ),
-+              (u32) __raw_readl( RX_BUFFER_INTERRUPT_LEVEL  ),
-+              (u32) __raw_readl( RX_SPDIF_DEBUG             ),
-+              (u32) __raw_readl( RX_SPDIF_DEBUG2            ) );
 +      
-+      procfs_buffer_size = iLen + sprintf( procfs_buffer + iLen, 
-+              "     INTERRUPT_CONTROL_STATUS  = 0x%08x\n"
-+              "     INTERRUPT_MASK            = 0x%08x\n"
-+              "     VERSION                   = 0x%08x\n"
-+              "     TX_DATA_IN_FORMAT         = 0x%08x\n"
-+              "     TX_CHANNELS_ENABLE        = 0x%08x\n"
-+              "     TX_WRITES_TO              = 0x%08x\n"
-+              "     RX_DATA_OUT_FORMAT        = 0x%08x\n"
-+              "     RX_CHANNELS_ENABLE        = 0x%08x\n"
-+              "     RX_READS_FROM             = 0x%08x\n"
-+              "     TX_CPU_DATA_WRITES_ALT    = 0x%08x\n"
-+              "     RX_CPU_DATA_READS_ALT     = 0x%08x\n"
-+              "     TX_CPU_DATA_WRITES        = 0x%08x\n"
-+              "     RX_CPU_DATA_READS         = 0x%08x\n"
-+              "\n"
-+              "--------------------------------------------------\n",
-+              (u32) __raw_readl( INTERRUPT_CONTROL_STATUS   ),
-+              (u32) __raw_readl( INTERRUPT_MASK             ),
-+              (u32) __raw_readl( VERSION                    ),
-+              (u32) __raw_readl( TX_DATA_IN_FORMAT          ),
-+              (u32) __raw_readl( TX_CHANNELS_ENABLE         ),
-+              (u32) __raw_readl( TX_WRITES_TO               ),
-+              (u32) __raw_readl( RX_DATA_OUT_FORMAT         ),
-+              (u32) __raw_readl( RX_CHANNELS_ENABLE         ),
-+              (u32) __raw_readl( RX_READS_FROM              ),
-+              (u32) __raw_readl( TX_CPU_DATA_WRITES_ALT     ),
-+              (u32) __raw_readl( RX_CPU_DATA_READS_ALT      ),
-+              (u32) __raw_readl( TX_CPU_DATA_WRITES         ),
-+              (u32) __raw_readl( RX_CPU_DATA_READS          ) );
++      int i;
++      int len = 0;
++      long unsigned *rd_monitor;
++      
++      
++      for (i=0; i < NO_MONITORS; i++)
++      {
++      rd_monitor = (long unsigned *) (AHB_MON_BASE + monitor[i].address);
++              len += sprintf(buf+len, "%s     CL:%ld EV:%ld hld:%ld slw:%lx tm:%ld\n", 
++                      monitor[i].name, 
++                      *rd_monitor, 
++                      *(rd_monitor+1),
++                      *(rd_monitor+2),
++                      *(rd_monitor+3),
++                      (*(rd_monitor+4) & 0xFFFF));
++      }
++      *eof=1;
++      return len;
 +}
++/*
++ * function to clear and start all the timers mainly together.
++ */
++#define MAX_CMD 5
++static int
++hipox_test_control(struct file *file, const char *buf, unsigned long count, void * data)
++{
++      int len;
++      int i;
++      long unsigned *rd_monitor;
++      unsigned cmd = 0;
++      
++      char local[MAX_CMD];
++      int result;
 +
++      if (count > MAX_CMD-1)
++              len= MAX_CMD-1;
++      else 
++              len=count;
++              
++      if (copy_from_user(&local, buf, len))
++              return -EFAULT;
++      
++      result=sscanf(local, "%d", &cmd);
++      
++      switch (cmd) 
++      {
++              case 0: 
++                      printk(KERN_INFO "hipox-test: stop command\n");
++                      break;
++              case 1:
++                      printk(KERN_INFO "hipox-test: run command\n");
++                      break;
++              case 2:
++                      printk(KERN_INFO "hipox-test: reset command\n");
++                      break;
++              default:
++                      printk(KERN_INFO "hipox-test: ignored command\n");
++                      return len;
++                      break;
++      }
++      
++      for (i=0; i < NO_MONITORS; i++)
++      {
++              rd_monitor = (long unsigned *) (AHB_MON_BASE + monitor[i].address);
++              *rd_monitor = (long unsigned) cmd;
++      }
++      return len;
++}
 +
-+void DumpI2SRegisters(void)
++
++/*
++ * The write function accepts a line as below:
++ * start_addr, end_addr, mode, burst, burst_mask, hprot, hprot_mask 
++ * expected string length is 10 + 10 + 3 + 3 + 4 + 3 + 4 < 40char.
++ * This is decoded by the scanf function into the separate items. - missing items are defaulted.
++ */
++ 
++#define MAX_STRING 40
++static int
++hipox_test_config_write(struct file *file, const char *buf, unsigned long count, void * data)
 +{
-+      RefreshI2SRegisters();
-+      printk( KERN_INFO "%s", procfs_buffer );  
-+      return;
++      
++      int len;        
++      int i = (int) data;
++      char local[MAX_STRING];
++      int result;
++      unsigned long * mon_ptr;
++
++      if (count > MAX_STRING-1)
++              len= MAX_STRING-1;
++      else 
++              len=count;
++              
++      if (copy_from_user(&local, buf, len))
++              return -EFAULT;
++      
++      /* extract value from buffer and store */
++      
++      result = sscanf(local, "%li,%li,%i,%i,%i,%i,%i", 
++              &monitor[i].low_add, 
++              &monitor[i].high_add, 
++              &monitor[i].mode, 
++              &monitor[i].burst, 
++              &monitor[i].burst_mask, 
++              &monitor[i].hprot,
++              &monitor[i].hprot_mask
++      );
++      if (result != 7)
++              return -EINVAL;
++              
++      /* load values on hardware */
++      
++      mon_ptr=(unsigned long *) (AHB_MON_BASE + monitor[i].address);
++
++      *(mon_ptr + 1) = monitor[i].mode & 0x3;
++      *(mon_ptr + 2) = monitor[i].low_add;
++      *(mon_ptr + 3) = monitor[i].high_add;
++      *(mon_ptr + 4) = ((monitor[i].burst & 0x7) << 4 | (monitor[i].burst_mask & 0x7));
++      *(mon_ptr + 5) = ((monitor[i].hprot & 0xf) << 4 | (monitor[i].hprot_mask &0xf));
++              
++      return len;
 +}
 +
-+
-+/**
-+ * This funtion is called when the /proc file is read
-+ *
-+ */
-+static ssize_t procfs_read(
-+      struct file *filp,      /* see include/linux/fs.h   */
-+      char *buffer,           /* buffer to fill with data */
-+      size_t length,          /* length of the buffer     */
-+      loff_t * offset)
++static int
++hipox_test_config_read(char *buf, char **start, off_t offset,
++                int count, int *eof, void *data)
 +{
-+      static int finished = 0;
-+
-+      /* 
-+       * We return 0 to indicate end of file, that we have
-+       * no more information. Otherwise, processes will
-+       * continue to read from us in an endless loop. 
-+       */
-+      if ( finished ) {
-+              printk(KERN_INFO "procfs_read: END\n");
-+              finished = 0;
-+              return 0;
-+      }
 +      
-+      finished = 1;
-+              
-+      /* 
-+       * We use put_to_user to copy the string from the kernel's
-+       * memory segment to the memory segment of the process
-+       * that called us. get_from_user, BTW, is
-+       * used for the reverse. 
-+       */
-+      if ( copy_to_user(buffer, procfs_buffer, procfs_buffer_size) ) {
-+              return -EFAULT;
-+      }
-+
-+      printk(KERN_INFO "procfs_read: read %lu bytes\n", procfs_buffer_size);
++      int len = 0;    
++      int i = (int) data;
++      
++      len += sprintf(buf+len, "name low  high  mode burst/mask hprot/mask\n"); 
 +
-+      return procfs_buffer_size;      /* Return the number of bytes "read" */
++      len += sprintf(buf+len, "%s     0x%08lx 0x%08lx %d 0x%x/0x%x 0x%x/0x%x\n", 
++              monitor[i].name, 
++              monitor[i].low_add, 
++              monitor[i].high_add, 
++              monitor[i].mode, 
++              monitor[i].burst, 
++              monitor[i].burst_mask, 
++              monitor[i].hprot,
++              monitor[i].hprot_mask);
++              
++              
++      *eof=1;
++      return len;
 +}
 +
-+/*
-+ * This function is called when /proc is written
-+ */
-+static ssize_t
-+procfs_write(struct file *file, const char *buffer, size_t len, loff_t * off)
++static int __init hipox_test_init(void)
 +{
-+      if ( len > PROCFS_MAX_SIZE )    {
-+              procfs_buffer_size = PROCFS_MAX_SIZE;
-+      }
-+      else    {
-+              procfs_buffer_size = len;
++      int rv=0;
++      int i;
++      
++      hipox_test_dir = proc_mkdir(MODULE_NAME, NULL);
++      if (hipox_test_dir == NULL) {
++              printk(KERN_ERR "hipox-test: unable to register /proc/usb-test\n");
++              rv= -ENOMEM;
++              goto out;
 +      }
 +      
-+      if ( copy_from_user(procfs_buffer, buffer, procfs_buffer_size) ) {
-+              return -EFAULT;
++      hipox_test_dir->owner= THIS_MODULE;
++      
++      proc_dir_usb_test_read = create_proc_entry("read", 0444, hipox_test_dir);
++      if (proc_dir_usb_test_read) {
++              proc_dir_usb_test_read->read_proc = hipox_test_read;
++      } else {
++              printk(KERN_ERR "hipox-test: unable to register /proc/usb-test/read\n");
++              rv = -ENOMEM;
++              goto no_read;
 +      }
 +
-+      printk(KERN_INFO "procfs_write: write %s\n",buffer);
-+      printk(KERN_INFO "procfs_write: write %lu bytes\n", procfs_buffer_size);
-+      
-+      return procfs_buffer_size;
-+}
++      /* create port write file entries */
++      for (i=0;i<NO_MONITORS;i++) 
++      {
++              rv = usb_test_write_entries(monitor[i].name, &hipox_test_config_write, &hipox_test_config_read, i);
++              if (rv < 0)
++              {
++                      while (i != 0)
++                      {
++                              i--;
++                              /* remove any allocated entries */
++                              remove_proc_entry (monitor[i].name, hipox_test_dir);
++                      } 
++                      goto no_write;
++              }
++      }
 +
-+/* 
-+ * This function decides whether to allow an operation
-+ * (return zero) or not allow it (return a non-zero
-+ * which indicates why it is not allowed).
-+ *
-+ * The operation can be one of the following values:
-+ * 0 - Execute (run the "file" - meaningless in our case)
-+ * 2 - Write (input to the kernel module)
-+ * 4 - Read (output from the kernel module)
-+ *
-+ * This is the real function that checks file
-+ * permissions. The permissions returned by ls -l are
-+ * for referece only, and can be overridden here.
-+ */
++      {
++              struct proc_dir_entry * entry = create_proc_entry("control", 0666, hipox_test_dir);
++              if (entry) {
++                      entry->write_proc = hipox_test_control;
++                      entry->owner = THIS_MODULE;
++                      return 0;
++              }
++              else
++              {
++                      goto no_control;
++              }
++      }
 +
-+static int module_permission(struct inode *inode, int op, struct nameidata *foo)
-+{
-+      /* 
-+       * We allow everybody to read from our module, but
-+       * only root (uid 0) may write to it 
-+       */
-+       if (op == 4 || (op == 2 && current->euid == 0)) {
-+               printk( KERN_INFO "Insufficient permissions\n");
-+              return 0;
-+       }
 +
-+      /* 
-+       * If it's anything else, access is denied 
-+       */
-+      return -EACCES;
-+}
++      printk(KERN_INFO "%s %s initialised\n", MODULE_NAME, MODULE_VERS);
 +
-+/* 
-+ * The file is opened - we don't really care about
-+ * that, but it does mean we need to increment the
-+ * module's reference count. 
-+ */
-+int procfs_open(struct inode *inode, struct file *file)
-+{
-+      u32 temp = 0;
-+      
-+      /* Open an entry on the proc filesystem */
-+      printk(KERN_INFO "I2S::procfs_open\n");
-+      try_module_get(THIS_MODULE);
++      return 0;
++
++      no_control:
++              for (i = NO_MONITORS; i != 0; )
++              {
++                      i--;
++                      /* remove any allocated entries */
++                      remove_proc_entry (monitor[i].name, hipox_test_dir);
++              } 
 +      
-+      // printk(KERN_INFO "I2S::pre-reg set..\n");
-+      // RefreshI2SRegisters();
++      no_write:
++              remove_proc_entry("read", hipox_test_dir);
++      no_read:
++              remove_proc_entry(MODULE_NAME, NULL);
++      out:
++              return rv;
++}
 +
-+      /* Setup the I2S TX Core... */
-+      temp  = 1                 << TX_CONTROL_ENABLE        |
-+              1                 << TX_CONTROL_FLUSH         |
-+              0                 << TX_CONTROL_MUTE          |
-+              0                 << TX_CONTROL_TRICK         |
-+              0                 << TX_CONTROL_SPEED         |
-+              1                 << TX_CONTROL_ABORT_DMA     |
-+              0                 << TX_CONTROL_AHB_ENABLE    |
-+              1                 << TX_CONTROL_QUAD_BURSTS;
-+      __raw_writel( temp, TX_CONTROL );
++
++static void __exit hipox_test_exit(void)
++{
++      int i;
 +      
-+      temp  = TRUE_I2S          << TX_SETUP_FORMAT          |
-+              I2S_SLAVE         << TX_SETUP_MODE            |
-+              0                 << TX_SETUP_FLOW_INVERT     |
-+              0                 << TX_SETUP_POS_EDGE        |
-+              0                 << TX_SETUP_CLOCK_STOP      |
-+              0                 << TX_SETUP_SPLIT_QUAD      |
-+              0                 << TX_SETUP_SPDIF_EN;
-+      __raw_writel( temp, TX_SETUP );
++      remove_proc_entry("control", hipox_test_dir);
 +      
-+      temp  = TWOS_COMPLIMENT   << TX_SETUP1_INPUT          |
-+              0                 << TX_SETUP1_REVERSE        |
-+              0                 << TX_SETUP1_INVERT         |
-+              0                 << TX_SETUP1_BIG_ENDIAN     |
-+              0                 << TX_SETUP1_QUAD_ENDIAN    |
-+              0                 << TX_SETUP1_QUAD_SAMPLES   |
-+              0                 << TX_SETUP1_FLOW_CONTROL;
-+      __raw_writel( temp, TX_SETUP1 );
++      for (i = 0; i < NO_MONITORS; i++)
++      {
++              remove_proc_entry(monitor[i].name, hipox_test_dir);
++      }
 +      
-+      /* Setup the I2S RX Core... */
++      remove_proc_entry("read", hipox_test_dir);
++      remove_proc_entry(MODULE_NAME, NULL);
++
++      printk(KERN_INFO "%s %s removed\n", MODULE_NAME, MODULE_VERS);
 +      
-+      printk(KERN_INFO "\n\nI2S::post-reg set..\n");
-+      RefreshI2SRegisters();
-+      return 0;
 +}
 +
-+/* 
-+ * The file is closed - again, interesting only because
-+ * of the reference count. 
-+ */
-+int procfs_close(struct inode *inode, struct file *file)
-+{
-+      printk(KERN_INFO "I2S::procfs_close\n");
-+      module_put(THIS_MODULE);
-+      return 0;               /* success */
-+}
 +
-+static struct file_operations File_Ops_4_Our_Proc_File = {
-+      .read    = procfs_read,
-+      .write   = procfs_write,
-+      .open    = procfs_open,
-+      .release = procfs_close,
-+};
++module_init(hipox_test_init);
++module_exit(hipox_test_exit);
 +
-+/* 
-+ * Inode operations for our proc file. We need it so
-+ * we'll have some place to specify the file operations
-+ * structure we want to use, and the function we use for
-+ * permissions. It's also possible to specify functions
-+ * to be called for anything else which could be done to
-+ * an inode (although we don't bother, we just put
-+ * NULL). 
-+ */
 +
-+static struct inode_operations Inode_Ops_4_Our_Proc_File = {
-+      .permission = module_permission,        /* check for permissions */
-+};
 +
-+/* 
-+ * Module initialization and cleanup 
-+ */
-+static int __init hipox_i2s_init_module(void)
-+{
-+      printk(KERN_INFO "I2S::init_module\n");
 +
-+      /* create the /proc file */
-+      Our_Proc_File = create_proc_entry(PROC_ENTRY_FILENAME, 0644, NULL);
-+      
-+      /* check if the /proc file was created successfuly */
-+      if (Our_Proc_File == NULL){
-+              printk(KERN_ALERT "Error: Could not initialize /proc/%s\n",
-+                     PROC_ENTRY_FILENAME);
-+              return -ENOMEM;
-+      }
-+      
-+      Our_Proc_File->owner      = THIS_MODULE;
-+      Our_Proc_File->proc_iops  = &Inode_Ops_4_Our_Proc_File;
-+      Our_Proc_File->proc_fops  = &File_Ops_4_Our_Proc_File;
-+      Our_Proc_File->mode       = S_IFREG | S_IRUGO | S_IWUSR;
-+      Our_Proc_File->uid        = 0;
-+      Our_Proc_File->gid        = 0;
-+      Our_Proc_File->size       = 80;
 +
-+      printk(KERN_INFO "/proc/%s created\n", PROC_ENTRY_FILENAME);
 +
-+      return 0;       /* success */
-+}
 +
-+static void __exit hipox_i2s_cleanup_module(void)
-+{
-+      printk(KERN_INFO "I2S::cleanup_module\n");
-+      remove_proc_entry(PROC_ENTRY_FILENAME, &proc_root);
-+      printk(KERN_INFO "/proc/%s removed\n", PROC_ENTRY_FILENAME);
-+}
 +
-+module_init(hipox_i2s_init_module);
-+module_exit(hipox_i2s_cleanup_module);
 +
 +
-diff -Nurd linux-2.6.24/arch/arm/mach-hipox/irq.c linux-2.6.24-oxe810/arch/arm/mach-hipox/irq.c
---- linux-2.6.24/arch/arm/mach-hipox/irq.c     1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mach-hipox/irq.c      2008-06-11 17:47:55.000000000 +0200
-@@ -0,0 +1,59 @@
++
++
++
++
++
++
++
++
++
++
++
++
+diff -Nurd linux-2.6.24.4/arch/arm/mach-hipox/hipox.c linux-2.6.24/arch/arm/mach-hipox/hipox.c
+--- linux-2.6.24.4/arch/arm/mach-hipox/hipox.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/mach-hipox/hipox.c   2010-01-14 14:01:15.000000000 +0100
+@@ -0,0 +1,1104 @@
 +/*
-+ *  linux/arch/arm/mach-hipox/irq.c
++ * linux/arch/arm/mach-hipox/hipox.c
++ *
++ * Copyright (C) 2005 Oxford Semiconductor Ltd
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License as published by
@@ -20331,966 +19427,1094 @@ diff -Nurd linux-2.6.24/arch/arm/mach-hipox/irq.c linux-2.6.24-oxe810/arch/arm/m
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 + */
++#include <linux/delay.h>
++#include <linux/platform_device.h>
++#include <linux/kernel.h>
 +#include <linux/init.h>
-+#include <linux/list.h>
-+#include <asm/hardware.h>
-+#include <asm/irq.h>
-+#include <asm/mach/irq.h>
++#include <linux/completion.h>
++#include <linux/serial.h>
++#include <linux/serial_core.h>
++#include <linux/serial_8250.h>
++
++#include <asm/sizes.h>
++#include <asm/setup.h>
++#include <asm/mach-types.h>
++#include <asm/mach/arch.h>
++#include <asm/mach/map.h>
++#include <asm/arch/hardware.h>
++#include <asm/arch/dma.h>
++
++#ifdef CONFIG_DO_MEM_TEST
++#include <linux/dma-mapping.h>
++#include <asm/io.h>
++#include <asm/arch/ahb_mon.h>
++#endif // CONFIG_DO_MEM_TEST
++
++#include <asm/io.h>
++
++#ifdef CONFIG_LEON_START_EARLY
++#include <asm/arch/leon.h>
++#include <asm/arch/leon-early-prog.h>
++#endif // CONFIG_LEON_START_EARLY
++
++#ifdef CONFIG_HIPOX_PCI_RESET_GPIO
++#if (CONFIG_HIPOX_PCI_RESET_GPIO < 32)
++#define PCI_RESET_NUM               CONFIG_HIPOX_PCI_RESET_GPIO
++#define PCI_RESET_PRISEL_REG        SYS_CTRL_GPIO_PRIMSEL_CTRL_0
++#define PCI_RESET_SECSEL_REG        SYS_CTRL_GPIO_SECSEL_CTRL_0
++#define PCI_RESET_TERSEL_REG        SYS_CTRL_GPIO_TERTSEL_CTRL_0
++#define PCI_RESET_SET_OE_REG        GPIO_A_OUTPUT_ENABLE_SET
++#define PCI_RESET_OUTPUT_SET_REG    GPIO_A_OUTPUT_SET
++#define PCI_RESET_OUTPUT_CLR_REG    GPIO_A_OUTPUT_CLEAR
++#else
++#define PCI_RESET_NUM               ((CONFIG_HIPOX_PCI_RESET_GPIO) - 32)
++#define PCI_RESET_PRISEL_REG        SYS_CTRL_GPIO_PRIMSEL_CTRL_1
++#define PCI_RESET_SECSEL_REG        SYS_CTRL_GPIO_SECSEL_CTRL_1
++#define PCI_RESET_TERSEL_REG        SYS_CTRL_GPIO_TERTSEL_CTRL_1
++#define PCI_RESET_SET_OE_REG        GPIO_B_OUTPUT_ENABLE_SET
++#define PCI_RESET_OUTPUT_SET_REG    GPIO_B_OUTPUT_SET
++#define PCI_RESET_OUTPUT_CLR_REG    GPIO_B_OUTPUT_CLEAR
++#endif
++
++#define PCI_RESET_MASK (1UL << (PCI_RESET_NUM))
++#endif // CONFIG_HIPOX_PCI_RESET_GPIO
++
++#define PCI_CLOCK_NUM               10
++#define PCI_CLOCK_PRISEL_REG        SYS_CTRL_GPIO_PRIMSEL_CTRL_0
++#define PCI_CLOCK_SET_OE_REG        GPIO_A_OUTPUT_ENABLE_SET
++#define PCI_CLOCK_MASK              (1UL << (PCI_CLOCK_NUM))
++
++#ifdef CONFIG_HIPOX_SATA_POWER_GPIO_1
++#if (CONFIG_HIPOX_SATA_POWER_GPIO_1 < 32)
++#define SATA_POWER_1_NUM            CONFIG_HIPOX_SATA_POWER_GPIO_1
++#define SATA_POWER_1_PRISEL_REG     SYS_CTRL_GPIO_PRIMSEL_CTRL_0
++#define SATA_POWER_1_SECSEL_REG     SYS_CTRL_GPIO_SECSEL_CTRL_0
++#define SATA_POWER_1_TERSEL_REG     SYS_CTRL_GPIO_TERTSEL_CTRL_0
++#define SATA_POWER_1_SET_OE_REG     GPIO_A_OUTPUT_ENABLE_SET
++#define SATA_POWER_1_OUTPUT_SET_REG GPIO_A_OUTPUT_SET
++#define SATA_POWER_1_OUTPUT_CLR_REG GPIO_A_OUTPUT_CLEAR
++#else
++#define SATA_POWER_1_NUM            ((CONFIG_HIPOX_SATA_POWER_GPIO_1) - 32)
++#define SATA_POWER_1_PRISEL_REG     SYS_CTRL_GPIO_PRIMSEL_CTRL_1
++#define SATA_POWER_1_SECSEL_REG     SYS_CTRL_GPIO_SECSEL_CTRL_1
++#define SATA_POWER_1_TERSEL_REG     SYS_CTRL_GPIO_TERTSEL_CTRL_1
++#define SATA_POWER_1_SET_OE_REG     GPIO_B_OUTPUT_ENABLE_SET
++#define SATA_POWER_1_OUTPUT_SET_REG GPIO_B_OUTPUT_SET
++#define SATA_POWER_1_OUTPUT_CLR_REG GPIO_B_OUTPUT_CLEAR
++#endif
++
++#define SATA_POWER_1_MASK   (1UL << (SATA_POWER_1_NUM))
++#endif // CONFIG_HIPOX_SATA_POWER_GPIO_1
++
++#ifdef CONFIG_HIPOX_SATA_POWER_GPIO_2
++#if (CONFIG_HIPOX_SATA_POWER_GPIO_2 < 32)
++#define SATA_POWER_2_NUM            CONFIG_HIPOX_SATA_POWER_GPIO_2
++#define SATA_POWER_2_PRISEL_REG     SYS_CTRL_GPIO_PRIMSEL_CTRL_0
++#define SATA_POWER_2_SECSEL_REG     SYS_CTRL_GPIO_SECSEL_CTRL_0
++#define SATA_POWER_2_TERSEL_REG     SYS_CTRL_GPIO_TERTSEL_CTRL_0
++#define SATA_POWER_2_SET_OE_REG     GPIO_A_OUTPUT_ENABLE_SET
++#define SATA_POWER_2_OUTPUT_SET_REG GPIO_A_OUTPUT_SET
++#define SATA_POWER_2_OUTPUT_CLR_REG GPIO_A_OUTPUT_CLEAR
++#else
++#define SATA_POWER_2_NUM            ((CONFIG_HIPOX_SATA_POWER_GPIO_2) - 32)
++#define SATA_POWER_2_PRISEL_REG     SYS_CTRL_GPIO_PRIMSEL_CTRL_1
++#define SATA_POWER_2_SECSEL_REG     SYS_CTRL_GPIO_SECSEL_CTRL_1
++#define SATA_POWER_2_TERSEL_REG     SYS_CTRL_GPIO_TERTSEL_CTRL_1
++#define SATA_POWER_2_SET_OE_REG     GPIO_B_OUTPUT_ENABLE_SET
++#define SATA_POWER_2_OUTPUT_SET_REG GPIO_B_OUTPUT_SET
++#define SATA_POWER_2_OUTPUT_CLR_REG GPIO_B_OUTPUT_CLEAR
++#endif
++
++#define SATA_POWER_2_MASK   (1UL << (SATA_POWER_2_NUM))
++#endif // CONFIG_HIPOX_SATA_POWER_GPIO_2
++
++#ifdef CONFIG_HIPOX_USB_HUB_RESET_GPIO
++#if (CONFIG_HIPOX_USB_HUB_RESET_GPIO < 32)
++#define USB_HUB_RESET_NUM            CONFIG_HIPOX_USB_HUB_RESET_GPIO
++#define USB_HUB_RESET_PRISEL_REG     SYS_CTRL_GPIO_PRIMSEL_CTRL_0
++#define USB_HUB_RESET_SECSEL_REG     SYS_CTRL_GPIO_SECSEL_CTRL_0
++#define USB_HUB_RESET_TERSEL_REG     SYS_CTRL_GPIO_TERTSEL_CTRL_0
++#define USB_HUB_RESET_SET_OE_REG     GPIO_A_OUTPUT_ENABLE_SET
++#define USB_HUB_RESET_OUTPUT_SET_REG GPIO_A_OUTPUT_SET
++#define USB_HUB_RESET_OUTPUT_CLR_REG GPIO_A_OUTPUT_CLEAR
++#else
++#define USB_HUB_RESET_NUM            ((CONFIG_HIPOX_USB_HUB_RESET_GPIO) - 32)
++#define USB_HUB_RESET_PRISEL_REG     SYS_CTRL_GPIO_PRIMSEL_CTRL_1
++#define USB_HUB_RESET_SECSEL_REG     SYS_CTRL_GPIO_SECSEL_CTRL_1
++#define USB_HUB_RESET_TERSEL_REG     SYS_CTRL_GPIO_TERTSEL_CTRL_1
++#define USB_HUB_RESET_SET_OE_REG     GPIO_B_OUTPUT_ENABLE_SET
++#define USB_HUB_RESET_OUTPUT_SET_REG GPIO_B_OUTPUT_SET
++#define USB_HUB_RESET_OUTPUT_CLR_REG GPIO_B_OUTPUT_CLEAR
++#endif
++
++#define USB_HUB_RESET_MASK    (1UL << (USB_HUB_RESET_NUM))
++#endif // CONFIG_HIPOX_USB_HUB_RESET_GPIO
++
++extern void hipox_init_irq(void);
++extern struct sys_timer hipox_timer;
++
++// The spinlock exported to allow atomic use of GPIO register set
++spinlock_t hipox_gpio_spinlock;
++
++// To hold LED inversion state
++int hipox_global_invert_leds = 0;
++#include <linux/module.h>
++EXPORT_SYMBOL(hipox_global_invert_leds);
++
++static struct map_desc hipox_io_desc[] __initdata = {
++    { CORE_MODULE_BASE,     __phys_to_pfn(CORE_MODULE_BASE_PA),     SZ_4K,   MT_DEVICE },
++    { APB_BRIDGE_A_BASE,    __phys_to_pfn(APB_BRIDGE_A_BASE_PA),    SZ_16M,  MT_DEVICE },
++    { STATIC_CONTROL_BASE,  __phys_to_pfn(STATIC_CONTROL_BASE_PA),  SZ_4K,   MT_DEVICE },
++    { STATIC_CS0_BASE,      __phys_to_pfn(STATIC_CS0_BASE_PA),      SZ_4K,   MT_DEVICE },
++    { STATIC_CS1_BASE,      __phys_to_pfn(STATIC_CS1_BASE_PA),      SZ_4K,   MT_DEVICE },
++    { STATIC_CS2_BASE,      __phys_to_pfn(STATIC_CS2_BASE_PA),      SZ_4K,   MT_DEVICE },
++    { APB_BRIDGE_B_BASE,    __phys_to_pfn(APB_BRIDGE_B_BASE_PA),    SZ_16M,  MT_DEVICE },
++    { USB_BASE,             __phys_to_pfn(USB_BASE_PA),             SZ_4M,   MT_DEVICE },
++    { MAC_BASE,             __phys_to_pfn(MAC_BASE_PA),             SZ_4M,   MT_DEVICE },
++    { ROM_BASE,             __phys_to_pfn(ROM_BASE_PA),             SZ_16K,  MT_DEVICE },
++    { PCI_CSRS_BASE,        __phys_to_pfn(PCI_CSRS_BASE_PA),        SZ_4K,   MT_DEVICE }
++#ifdef CONFIG_SUPPORT_LEON
++#if (CONFIG_LEON_PAGES == 1)
++   ,{ LEON_IMAGE_BASE,                        __phys_to_pfn(LEON_IMAGE_BASE_PA),                      SZ_4K, MT_DEVICE }
++#elif (CONFIG_LEON_PAGES == 2)
++   ,{ LEON_IMAGE_BASE,                        __phys_to_pfn(LEON_IMAGE_BASE_PA),                      SZ_8K, MT_DEVICE }
++#elif (CONFIG_LEON_PAGES == 3)
++   ,{ LEON_IMAGE_BASE,                    __phys_to_pfn(LEON_IMAGE_BASE_PA),                  SZ_8K, MT_DEVICE }
++   ,{ LEON_IMAGE_BASE+0x2000, __phys_to_pfn(LEON_IMAGE_BASE_PA+0x2000),       SZ_4K, MT_DEVICE }
++#elif (CONFIG_LEON_PAGES == 4)
++   ,{ LEON_IMAGE_BASE,                    __phys_to_pfn(LEON_IMAGE_BASE_PA),                  SZ_8K, MT_DEVICE }
++   ,{ LEON_IMAGE_BASE+0x2000, __phys_to_pfn(LEON_IMAGE_BASE_PA+0x2000),       SZ_8K, MT_DEVICE }
++#else
++#error "Unsupported number of Leon code pages"
++#endif // CONFIG_LEON_PAGES
++#endif // CONFIG_SUPPORT_LEON
++      /*
++       * Upto 8 pages for GMAC/DMA descriptors plus ARM/Leon TSO workspace if
++       * Leon TSO is in use
++       */
++   ,{ SRAM_BASE,            __phys_to_pfn(SRAM_PA),                 SZ_16K, MT_DEVICE }
++   ,{ SRAM_BASE+0x4000,     __phys_to_pfn(SRAM_PA+0x4000),          SZ_16K, MT_DEVICE }
++};
++
++static struct resource usb_resources[] = {
++      [0] = {
++              .start          = USB_BASE_PA,
++              .end            = USB_BASE_PA + 0x10000 - 1,
++              .flags          = IORESOURCE_MEM,
++      },
++      [1] = {
++              .start          = USB_FS_INTERRUPT,
++              .end            = USB_FS_INTERRUPT,
++              .flags          = IORESOURCE_IRQ,
++      },
++};
++
++static u64 usb_dmamask = ~(u32)0;
++
++static struct platform_device usb_device = {
++      .name           = "hipox-ehci",
++      .id             = 0,
++      .dev = {
++              .dma_mask               = &usb_dmamask,
++              .coherent_dma_mask      = 0xffffffff,
++      },
++      .num_resources  = ARRAY_SIZE(usb_resources),
++      .resource       = usb_resources,
++};
++
++static struct platform_device *platform_devices[] __initdata = {
++      &usb_device,
++};
++
++#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ)
++
++#define INT_UART_BASE_BAUD (NOMINAL_SYSCLK)
++
++#ifdef CONFIG_ARCH_HIPOX_UART1
++static struct uart_port internal_serial_port_1 = {
++      .membase        = (char *)(UART_1_BASE),
++      .mapbase        = UART_1_BASE_PA,
++      .irq            = UART_1_INTERRUPT,
++      .flags          = STD_COM_FLAGS,
++      .iotype         = UPIO_MEM,
++      .regshift       = 0,
++      .uartclk        = INT_UART_BASE_BAUD,
++      .line           = 0,
++      .type           = PORT_16550A,
++      .fifosize       = 16
++};
++#endif // CONFIG_ARCH_HIPOX_UART1
 +
-+static void HIPOX_mask_irq(unsigned int irq)
-+{
-+    *((volatile unsigned long*)(RPS_IRQ_DISABLE)) = (1UL << irq);
-+}
++#ifdef CONFIG_ARCH_HIPOX_UART2
++static struct uart_port internal_serial_port_2 = {
++      .membase        = (char *)(UART_2_BASE),
++      .mapbase        = UART_2_BASE_PA,
++      .irq            = UART_2_INTERRUPT,
++      .flags          = STD_COM_FLAGS,
++      .iotype         = UPIO_MEM,
++      .regshift       = 0,
++      .uartclk        = INT_UART_BASE_BAUD,
++      .line           = 0,
++      .type           = PORT_16550A,
++      .fifosize       = 16
++};
++#endif // CONFIG_ARCH_HIPOX_UART2
 +
-+static void HIPOX_unmask_irq(unsigned int irq)
-+{
-+    *((volatile unsigned long*)RPS_IRQ_ENABLE) = (1UL << irq);
-+}
++#ifdef CONFIG_ARCH_HIPOX_UART3
++static struct uart_port internal_serial_port_3 = {
++      .membase        = (char *)(UART_3_BASE),
++      .mapbase        = UART_3_BASE_PA,
++      .irq            = UART_3_INTERRUPT,
++      .flags          = STD_COM_FLAGS,
++      .iotype         = UPIO_MEM,
++      .regshift       = 0,
++      .uartclk        = INT_UART_BASE_BAUD,
++      .line           = 0,
++      .type           = PORT_16550A,
++      .fifosize       = 16
++};
++#endif // CONFIG_ARCH_HIPOX_UART3
 +
-+static struct irq_chip HIPOX_chip = {
-+      .name   = "HIPOX",
-+    .ack      = HIPOX_mask_irq,
-+    .mask     = HIPOX_mask_irq,
-+    .unmask = HIPOX_unmask_irq,
++#ifdef CONFIG_ARCH_HIPOX_UART4
++static struct uart_port internal_serial_port_4 = {
++      .membase        = (char *)(UART_4_BASE),
++      .mapbase        = UART_4_BASE_PA,
++      .irq            = UART_4_INTERRUPT,
++      .flags          = STD_COM_FLAGS,
++      .iotype         = UPIO_MEM,
++      .regshift       = 0,
++      .uartclk        = INT_UART_BASE_BAUD,
++      .line           = 0,
++      .type           = PORT_16550A,
++      .fifosize       = 16
 +};
++#endif // CONFIG_ARCH_HIPOX_UART4
 +
-+void __init hipox_init_irq(void)
++static void __init hipox_mapio(void)
 +{
-+    unsigned irq;
-+
-+    // Disable all IRQs
-+    *((volatile unsigned long*)(RPS_IRQ_DISABLE)) = ~0UL;
++    unsigned int uart_line=0;
 +
-+    // Disable FIQ
-+    *((volatile unsigned long*)(RPS_FIQ_DISABLE)) = ~0UL;
++//printk("hipox_mapio()\n");
 +
-+    // Initialise IRQ tracking structures
-+    for (irq=0; irq < NR_IRQS; irq++)
-+    {
-+        set_irq_chip(irq, &HIPOX_chip);
-+        set_irq_handler(irq, handle_level_irq);
-+        set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
-+    }
-+}
++    // Setup kernel mappings for hardware cores
++    iotable_init(hipox_io_desc, ARRAY_SIZE(hipox_io_desc));
 +
-diff -Nurd linux-2.6.24/arch/arm/mach-hipox/leds.c linux-2.6.24-oxe810/arch/arm/mach-hipox/leds.c
---- linux-2.6.24/arch/arm/mach-hipox/leds.c    1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mach-hipox/leds.c     2008-06-11 17:47:55.000000000 +0200
-@@ -0,0 +1,212 @@
-+/*
-+ * linux/arch/arm/mach-hipox/leds.c
-+ *
-+ * Copyright (C) 2005 Oxford Semiconductor Ltd
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+#define DEBUG
++#ifdef CONFIG_ARCH_HIPOX_FPGA    
++    // Setup the ARM926-EJ-S integrator module clock and bus clock divider
++    asm volatile(
++        "mov r3,%2,LSL #4;"     /* Bus clock divider = ((n+1) << 4) */
++        "sub r3,r3,#16;"
++        "mov r0,%1;"            /* Processor clock frequency */
++        "sub r0,r0,#8;"         /* correction for MHz */
++        "and r0,r0,#0xFF;"      /* ensure byte value */
++        "mov r2,%0;"            /* read CM base value */
++        "ldr r1,[r2,#8];"       /* read CM_OSC */
++        "bic r1,r1,#0x0FF;"     /* clear bottom byte r1 */
++        "orr r1,r1,r0;"         /* write in new clock values */
++        "ldr r4,[r2,#0x24];"    /* read CM_INIT */
++        "bic r4,r4,#0x070;"     /* clear bits [6:4] */
++        "orr r4,r4,r3;"         /* write in new clock values */
++        "mov r0,#0xA000;"
++        "orr r0,r0,#0x5F;"      /* build 0xA05F in r0 */
++        "str r0,[r2,#0x14];"    /* write to unlock CM_LOCK */
++        "str r1,[r2,#8];"       /* write value back */
++        "str r4,[r2,#0x24];"    /* write HCLK value back */
++        "str r1,[r2,#0x14];"    /* write in any value to relock CM_LOCK */
++        :
++        : "r" (CORE_MODULE_BASE), "r" (CONFIG_HIPOX_CORE_CLK), "r" (CONFIG_HIPOX_CORE_BUS_CLK_DIV)
++        : "r0","r1","r2","r3","r4");
++#endif // CONFIG_ARCH_HIPOX_FPGA
 +
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/timer.h>
-+#include <linux/interrupt.h>
++#ifdef CONFIG_HIPOX_VERSION_0X800
++    // Configure the DDR controller arbitration scheme
++    *(volatile u32*)DDR_ARB_REG = ((1UL << DDR_ARB_DATDIR_NCH_BIT) |
++                                   (1UL << DDR_ARB_DATDIR_EN_BIT)  |
++                                   (1UL << DDR_ARB_REQAGE_EN_BIT)  |
++                                   (1UL << DDR_ARB_LRUBANK_EN_BIT) |
++                                   (1UL << DDR_ARB_MIDBUF_BIT));
 +
-+#include <linux/platform_device.h>
++    // Setup the DDR client read buffers
++    // NB 0X800 ASIC bug means DMA read buffers should never be enabled
++    *(volatile u32*)DDR_AHB_REG = ((1UL << DDR_AHB_NO_RCACHE_ARMD_BIT)  |
++                                   /*(1UL << DDR_AHB_NO_RCACHE_ARMI_BIT)  |*/
++                                   (1UL << DDR_AHB_NO_RCACHE_COPRO_BIT) |
++                                   (1UL << DDR_AHB_NO_RCACHE_DMAA_BIT)  |
++                                   (1UL << DDR_AHB_NO_RCACHE_DMAB_BIT)  |
++                                   /* (1UL << DDR_AHB_NO_RCACHE_PCI_BIT)   |
++                                   (1UL << DDR_AHB_NO_RCACHE_GMAC_BIT)  |*/
++                                   (1UL << DDR_AHB_NO_RCACHE_USB_BIT));
 +
++    // Ignore HPROT for all clients except ARM data, as ARM Linux interrupt
++      // latency will mask any slight delay in data written by cores getting to
++      // memory after the core raises an interrupt
++      *(volatile u32*)DDR_AHB2_REG = ((1UL << DDR_AHB2_IGNORE_HPROT_ARMI_BIT)  |
++                                                                       (1UL << DDR_AHB2_IGNORE_HPROT_COPRO_BIT) |
++                                                                       (1UL << DDR_AHB2_IGNORE_HPROT_DMAA_BIT)  |
++                                                                       (1UL << DDR_AHB2_IGNORE_HPROT_DMAB_BIT)  |
++                                                                       (1UL << DDR_AHB2_IGNORE_HPROT_PCI_BIT)   |
++                                                                       (1UL << DDR_AHB2_IGNORE_HPROT_GMAC_BIT)  |
++                                                                       (1UL << DDR_AHB2_IGNORE_HPROT_USB_BIT));
++#elif CONFIG_HIPOX_VERSION_0X810
++    // Configure the DDR controller arbitration scheme
++    *(volatile u32*)DDR_ARB_REG = ((1UL << DDR_ARB_DATDIR_NCH_BIT) |
++                                   (1UL << DDR_ARB_DATDIR_EN_BIT)  |
++                                   (1UL << DDR_ARB_REQAGE_EN_BIT)  |
++                                   (1UL << DDR_ARB_LRUBANK_EN_BIT) |
++                                   (1UL << DDR_ARB_MIDBUF_BIT));
 +
-+#include <linux/leds.h>
-+ 
-+#include <asm/hardware.h>
++      // Configure read buffers - Do not disable any read buffers
++      *(volatile u32*)DDR_AHB_REG = 0UL;
 +
-+#define DEBUG_PRINT(A) printk(KERN_NOTICE A)
++      // Configure wrapping - Ignore wrap
++      // Configure HPROT - Ignore all HPROT except ARM data
++      *(volatile u32*)DDR_AHB2_REG = ((1UL << DDR_AHB2_IGNORE_WRAP_ARMD_BIT)   |
++                                    (1UL << DDR_AHB2_IGNORE_WRAP_ARMI_BIT)   |
++                                    (1UL << DDR_AHB2_IGNORE_WRAP_COPRO_BIT)  |
++                                    (1UL << DDR_AHB2_IGNORE_WRAP_DMAA_BIT)   |
++                                    (1UL << DDR_AHB2_IGNORE_WRAP_DMAB_BIT)   |
++                                    (1UL << DDR_AHB2_IGNORE_WRAP_PCI_BIT)    |
++                                    (1UL << DDR_AHB2_IGNORE_WRAP_GMAC_BIT)   |
++                                    (1UL << DDR_AHB2_IGNORE_WRAP_US_BIT)     |
++                                    (1UL << DDR_AHB2_IGNORE_HPROT_ARMI_BIT)  |
++                                    (1UL << DDR_AHB2_IGNORE_HPROT_COPRO_BIT) |
++                                    (1UL << DDR_AHB2_IGNORE_HPROT_DMAA_BIT)  |
++                                    (1UL << DDR_AHB2_IGNORE_HPROT_DMAB_BIT)  |
++                                    (1UL << DDR_AHB2_IGNORE_HPROT_PCI_BIT)   |
++                                    (1UL << DDR_AHB2_IGNORE_HPROT_GMAC_BIT)  |
++                                    (1UL << DDR_AHB2_IGNORE_HPROT_USB_BIT));
 +
-+#define writel(data,address) (*(volatile u32 *) address = data)
-+#define readl(address)       (*(volatile u32 *) address)
++      // Configure burst ordering - Do not disable burst ordering
++      // Configure non-cachable - Do not prevent non-cachable accesses from using read buffers
++      *(volatile u32*)DDR_AHB3_REG = 0UL;
 +
-+/* run pwm refresh at approximately 100Hz to avoid flicker */
-+/* resolution is 8bits, sys clock 200MHz divider is therefore 7812 less 1 cycle */
-+#define PWM_PERIOD  (7811)
++      // Configure read buffer timeout - Do not enable read buffer invalidate after timeout
++      // Configure write behind - Enable write behind coherency
++      *(volatile u32*)DDR_AHB4_REG = ((1UL << DDR_AHB4_EN_WRBEHIND_ARMD_BIT)  |
++                                                                       (1UL << DDR_AHB4_EN_WRBEHIND_ARMI_BIT)  |
++                                                                       (1UL << DDR_AHB4_EN_WRBEHIND_COPRO_BIT) |
++                                                                       (1UL << DDR_AHB4_EN_WRBEHIND_DMAA_BIT)  |
++                                                                       (1UL << DDR_AHB4_EN_WRBEHIND_DMAB_BIT)  |
++                                                                       (1UL << DDR_AHB4_EN_WRBEHIND_PCI_BIT)   |
++                                                                       (1UL << DDR_AHB4_EN_WRBEHIND_GMAC_BIT)  |
++                                                                       (1UL << DDR_AHB4_EN_WRBEHIND_USB_BIT));
 +
-+#define MAX_PWMS     16
++#endif // CONFIG_HIPOX_VERSION_0X8xx
 +
-+static void ramp_power_on_leds(unsigned long data);
++    // Enable all DDR client interfaces
++    *(volatile u32*)DDR_BLKEN_REG |= (((1UL << DDR_BLKEN_CLIENTS_NUM_BITS) - 1) << DDR_BLKEN_CLIENTS_BIT);
 +
-+DEFINE_TIMER (power_ramp_timer, ramp_power_on_leds, 0, 0);
++#ifdef CONFIG_ARCH_HIPOX_UART1
++    // Block reset UART1
++    *(volatile u32*)SYS_CTRL_RSTEN_SET_CTRL = (1UL << SYS_CTRL_RSTEN_UART1_BIT);
++    *(volatile u32*)SYS_CTRL_RSTEN_CLR_CTRL = (1UL << SYS_CTRL_RSTEN_UART1_BIT);
 +
-+enum { POWER_ON,
-+      NUMBER_LEDS};
-+      
-+static struct platform_device *hipox_leds;    
-+static u16 offset[NUMBER_LEDS] = {25};
++    // Route UART1 SOUT onto external pin
++    *(volatile u32*)SYS_CTRL_GPIO_PRIMSEL_CTRL_0 &= ~0x80000000;
++    *(volatile u32*)SYS_CTRL_GPIO_SECSEL_CTRL_0  &= ~0x80000000;
++    *(volatile u32*)SYS_CTRL_GPIO_TERTSEL_CTRL_0 |=  0x80000000;
 +
-+static u16 led [NUMBER_LEDS];
++    // Route UART1 SIN onto external pin
++    *(volatile u32*)SYS_CTRL_GPIO_PRIMSEL_CTRL_1 &= ~0x00000001;
++    *(volatile u32*)SYS_CTRL_GPIO_SECSEL_CTRL_1  &= ~0x00000001;
++    *(volatile u32*)SYS_CTRL_GPIO_TERTSEL_CTRL_1 |=  0x00000001;
 +
-+#define MAX_BRIGHTNESS   255
++    // Setup GPIO line direction for UART1 SOUT
++    *(volatile u32*)GPIO_A_OUTPUT_ENABLE_SET   |= 0x80000000;
 +
-+static void set_led(u16 led, u16 value)
-+{
-+      u16 led_index = offset[led] % MAX_PWMS;
-+      
-+      writel(value, (PWM_DATA_REGISTER_BASE+4*led_index));
-+      
-+}
++    // Setup GPIO line direction for UART1 SIN
++    *(volatile u32*)GPIO_B_OUTPUT_ENABLE_CLEAR |= 0x00000001;
 +
-+static void ramp_power_on_leds(unsigned long data)
-+{
-+      if (led[POWER_ON] < MAX_BRIGHTNESS) {
-+               set_led(POWER_ON, ++led[POWER_ON]);
-+               mod_timer(&power_ramp_timer, (power_ramp_timer.expires + msecs_to_jiffies(64)) );
-+      }
-+      else del_timer(&power_ramp_timer);
-+}
++#ifdef CONFIG_ARCH_HIPOX_UART1_MODEM
++    // Route UART1 modem control lines onto external pins
++    *(volatile u32*)SYS_CTRL_GPIO_PRIMSEL_CTRL_0 &= ~0x78000000;
++    *(volatile u32*)SYS_CTRL_GPIO_SECSEL_CTRL_0  &= ~0x78000000;
++    *(volatile u32*)SYS_CTRL_GPIO_TERTSEL_CTRL_0 |=  0x78000000;
 +
-+static void hipoxled_power_on_set(struct led_classdev *led_cdev, enum led_brightness value)
-+{
-+      if (value == 0) {
-+              current_bright = 0;
-+              led[POWER_ON]=0;
-+          set_led(POWER_ON, 0);
-+              
-+      }
-+      else
-+      {
-+              power_ramp_timer.expires = jiffies + msecs_to_jiffies(64);
-+              add_timer(&power_ramp_timer);
-+      }
-+}
++    *(volatile u32*)SYS_CTRL_GPIO_PRIMSEL_CTRL_1 &= ~0x00000006;
++    *(volatile u32*)SYS_CTRL_GPIO_SECSEL_CTRL_1  &= ~0x00000006;
++    *(volatile u32*)SYS_CTRL_GPIO_TERTSEL_CTRL_1 |=  0x00000006;
 +
-+static struct led_classdev hipox_power_on_led = {
-+      .name                   = "hipox:power_on",
-+      .brightness_set         = hipoxled_power_on_set,
-+};
++    // Setup GPIO line directions for UART1 modem control lines
++    *(volatile u32*)GPIO_A_OUTPUT_ENABLE_SET   |= 0x08000000;
++    *(volatile u32*)GPIO_A_OUTPUT_ENABLE_CLEAR |= 0x70000000;
 +
++    *(volatile u32*)GPIO_B_OUTPUT_ENABLE_SET   |= 0x00000004;
++    *(volatile u32*)GPIO_B_OUTPUT_ENABLE_CLEAR |= 0x00000002;
++#endif // CONFIG_ARCH_HIPOX_UART1_MODEM
 +
-+#ifdef CONFIG_PM
++    // Give Linux a contiguous numbering scheme for available UARTs
++    internal_serial_port_1.line = uart_line++;
++    early_serial_setup(&internal_serial_port_1);
++#endif // CONFIG_ARCH_HIPOX_UART1
 +
-+// TODO implement led suspend operation on NAS
-+static int hipoxled_suspend(struct platform_device *dev, pm_message_t state)
-+{
-+#ifdef CONFIG_LEDS_TRIGGERS
-+      if (hipox_amber_led.trigger && strcmp(hipox_amber_led.trigger->name, "sharpsl-charge"))
-+#endif
-+              led_classdev_suspend(&hipox_amber_led);
-+      led_classdev_suspend(&hipox_green_led);
-+      return 0;
-+}
-+// TODO implement led resume operation on NAS
-+static int hipoxled_resume(struct platform_device *dev)
-+{
-+      led_classdev_resume(&hipox_amber_led);
-+      led_classdev_resume(&hipox_green_led);
-+      return 0;
-+}
-+#endif
++#ifdef CONFIG_ARCH_HIPOX_UART2
++    // Block reset UART2
++    *(volatile u32*)SYS_CTRL_RSTEN_SET_CTRL = (1UL << SYS_CTRL_RSTEN_UART2_BIT);
++    *(volatile u32*)SYS_CTRL_RSTEN_CLR_CTRL = (1UL << SYS_CTRL_RSTEN_UART2_BIT);
 +
-+static int hipoxled_probe(struct platform_device *pdev)
-+{
-+      int ret;
-+      int i;
++    // Route UART2 SIN/SOUT onto external pin
++    *(volatile u32*)SYS_CTRL_GPIO_PRIMSEL_CTRL_0 &= ~0x00500000;
++    *(volatile u32*)SYS_CTRL_GPIO_SECSEL_CTRL_0  &= ~0x00500000;
++    *(volatile u32*)SYS_CTRL_GPIO_TERTSEL_CTRL_0 |=  0x00500000;
 +
-+      writel(PWM_PERIOD, PWM_CLOCK_REGISTER);
++    // Setup GPIO line directions for UART2 SIN/SOUT
++    *(volatile u32*)GPIO_A_OUTPUT_ENABLE_SET   |= 0x00100000;
++    *(volatile u32*)GPIO_A_OUTPUT_ENABLE_CLEAR |= 0x00400000;
 +
-+      
-+      /* enable PWM drives outputs */
-+      for (i=0; i < NUMBER_LEDS ; ++i)
-+      {
-+              if (offset[i] < 32) {
-+                      writel(readl(SYS_CTRL_GPIO_PWMSEL_CTRL_0) | (1 << offset[i]), SYS_CTRL_GPIO_PWMSEL_CTRL_0); 
-+              }
-+              else {
-+                      writel(readl(SYS_CTRL_GPIO_PWMSEL_CTRL_1) | (1 << (offset[i]% 32)), SYS_CTRL_GPIO_PWMSEL_CTRL_1);
-+              }
-+      }
++#ifdef CONFIG_ARCH_HIPOX_UART2_MODEM
++    // Route UART2 modem control lines onto external pins
++    *(volatile u32*)SYS_CTRL_GPIO_PRIMSEL_CTRL_0 &= ~0x07800300;
++    *(volatile u32*)SYS_CTRL_GPIO_SECSEL_CTRL_0  &= ~0x07800300;
++    *(volatile u32*)SYS_CTRL_GPIO_TERTSEL_CTRL_0 |=  0x07800300;
 +
-+      ret = led_classdev_register(&pdev->dev, &hipox_power_on_led);
-+      
-+      if (ret < 0) goto error_1;
-+      
-+      return ret;
-+      
-+error_1:              
-+      return ret;
-+}
++    // Setup GPIO line directions for UART2 modem control lines
++    *(volatile u32*)GPIO_A_OUTPUT_ENABLE_SET   |= 0x02000200;
++    *(volatile u32*)GPIO_A_OUTPUT_ENABLE_CLEAR |= 0x05800100;
++#endif // CONFIG_ARCH_HIPOX_UART2_MODEM
 +
-+static int hipoxled_remove(struct platform_device *pdev)
-+{
-+      int i;
-+      
-+      led_classdev_unregister(&hipox_power_on_led);
++    // Give Linux a contiguous numbering scheme for available UARTs
++    internal_serial_port_2.line = uart_line++;
++    early_serial_setup(&internal_serial_port_2);
++#endif // CONFIG_ARCH_HIPOX_UART2
 +
-+      /* disable PWM drives outputs */
-+      for (i=0; i < NUMBER_LEDS ; ++i)
-+      {
-+              if (offset[i] < 32) {
-+                      writel(readl(SYS_CTRL_GPIO_PWMSEL_CTRL_0) & ~((u32)1 << offset[i]), SYS_CTRL_GPIO_PWMSEL_CTRL_0); 
-+              }
-+              else {
-+                      writel(readl(SYS_CTRL_GPIO_PWMSEL_CTRL_1) & ~((u32)1 << (offset[i]% 32)), SYS_CTRL_GPIO_PWMSEL_CTRL_1);
-+              }
-+      }
-+      
-+      writel(PWM_CLOCK_REGISTER, 0);
-+      
-+      return 0;
-+}
++#ifdef CONFIG_ARCH_HIPOX_UART3
++    // Block reset UART3
++    *(volatile u32*)SYS_CTRL_RSTEN_SET_CTRL = (1UL << SYS_CTRL_RSTEN_UART3_BIT);
++    *(volatile u32*)SYS_CTRL_RSTEN_CLR_CTRL = (1UL << SYS_CTRL_RSTEN_UART3_BIT);
 +
++    // Route UART3 SIN/SOUT onto external pin
++    *(volatile u32*)SYS_CTRL_GPIO_PRIMSEL_CTRL_0 &= ~0x000000C0;
++    *(volatile u32*)SYS_CTRL_GPIO_SECSEL_CTRL_0  &= ~0x000000C0;
++    *(volatile u32*)SYS_CTRL_GPIO_TERTSEL_CTRL_0 |=  0x000000C0;
 +
-+static struct platform_driver hipoxled_driver = {
-+      .probe          = hipoxled_probe,
-+      .remove         = hipoxled_remove,
-+#ifdef CONFIG_PM
-+      .suspend        = hipoxled_suspend,
-+      .resume         = hipoxled_resume,
-+#endif
-+      .driver         = {
-+              .name           = "hipox-leds",
-+              .owner      = THIS_MODULE,
-+      },
-+};
++    // Setup GPIO line directions for UART3 SIN/SOUT
++    *(volatile u32*)GPIO_A_OUTPUT_ENABLE_SET   |= 0x00000080;
++    *(volatile u32*)GPIO_A_OUTPUT_ENABLE_CLEAR |= 0x00000040;
 +
-+static int __init hipoxled_init(void)
-+{
-+      int ret;
++    // Enable UART3 interrupt
++    *(volatile u32*)SYS_CTRL_UART_CTRL |= (1UL << SYS_CTRL_UART3_IQ_EN);
 +
-+      ret = platform_driver_register(&hipoxled_driver);
-+      
-+      
-+      
-+      /* now register the devices on the bus so they can be associated with the driver */
-+      if (!ret) 
-+                      hipox_leds=platform_device_register_simple("hipox-leds", -1, NULL, 0);
-+      return ret;
-+}
++#ifdef CONFIG_ARCH_HIPOX_UART3_MODEM
++    // Route UART3 modem control lines onto external pins
++    *(volatile u32*)SYS_CTRL_GPIO_PRIMSEL_CTRL_0 &= ~0x0000003f;
++    *(volatile u32*)SYS_CTRL_GPIO_SECSEL_CTRL_0  &= ~0x0000003f;
++    *(volatile u32*)SYS_CTRL_GPIO_TERTSEL_CTRL_0 |=  0x0000003f;
 +
-+static void __exit hipoxled_exit(void)
-+{
-+      if (hipox_leds) {
-+              platform_device_unregister(hipox_leds);
-+      }
++    // Setup GPIO line directions for UART3 modem control lines
++    *(volatile u32*)GPIO_A_OUTPUT_ENABLE_SET   |= 0x00000030;
++    *(volatile u32*)GPIO_A_OUTPUT_ENABLE_CLEAR |= 0x0000000f;
++#endif // CONFIG_ARCH_HIPOX_UART3_MODEM
 +
-+      platform_driver_unregister(&hipoxled_driver);
-+}
++    // Give Linux a contiguous numbering scheme for available UARTs
++    internal_serial_port_3.line = uart_line++;
++    early_serial_setup(&internal_serial_port_3);
++#endif // CONFIG_ARCH_HIPOX_UART3
 +
-+module_init(hipoxled_init);
-+module_exit(hipoxled_exit);
++#ifdef CONFIG_ARCH_HIPOX_UART4
++    // Block reset UART4
++    *(volatile u32*)SYS_CTRL_RSTEN_SET_CTRL = (1UL << SYS_CTRL_RSTEN_UART4_BIT);
++    *(volatile u32*)SYS_CTRL_RSTEN_CLR_CTRL = (1UL << SYS_CTRL_RSTEN_UART4_BIT);
 +
-+MODULE_AUTHOR("John Larkworthy <john.larkworthy@oxsem.com");
-+MODULE_DESCRIPTION("HIPOX front panel LED driver");
-+MODULE_LICENSE("GPL");
-diff -Nurd linux-2.6.24/arch/arm/mach-hipox/ledtrig_sata.c linux-2.6.24-oxe810/arch/arm/mach-hipox/ledtrig_sata.c
---- linux-2.6.24/arch/arm/mach-hipox/ledtrig_sata.c    1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mach-hipox/ledtrig_sata.c     2008-06-11 17:47:55.000000000 +0200
-@@ -0,0 +1,69 @@
-+/*
-+ * linux/arch/arm/mach-hipox/leds.c
-+ *
-+ * Copyright (C) 2006 Oxford Semiconductor Ltd
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
++    // Enable UART4 interrupt
++    *(volatile u32*)SYS_CTRL_UART_CTRL |= (1UL << SYS_CTRL_UART4_IQ_EN);
 +
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/timer.h>
-+#include <linux/leds.h>
++    // Enable UART4 to override PCI functions onto GPIOs
++    *(volatile u32*)SYS_CTRL_UART_CTRL |= (1UL << SYS_CTRL_UART4_NOT_PCI_MODE);
 +
-+static void ledtrig_ide_timerfunc(unsigned long data);
++    internal_serial_port_4.line = uart_line++;
++    early_serial_setup(&internal_serial_port_4);
++#endif // CONFIG_ARCH_HIPOX_UART4
 +
-+DEFINE_LED_TRIGGER(ledtrig_ide);
-+static DEFINE_TIMER(ledtrig_ide_timer, ledtrig_ide_timerfunc, 0, 0);
-+static int ide_activity;
-+static int ide_lastactivity;
++#ifdef CONFIG_PCI
++    // Block reset PCI core
++    *(volatile u32*)SYS_CTRL_RSTEN_SET_CTRL = (1UL << SYS_CTRL_RSTEN_PCI_BIT);
++    *(volatile u32*)SYS_CTRL_RSTEN_CLR_CTRL = (1UL << SYS_CTRL_RSTEN_PCI_BIT);
 +
-+void ledtrig_sata_activity(void)
-+{
-+      ide_activity++;
-+      if (!timer_pending(&ledtrig_ide_timer))
-+              mod_timer(&ledtrig_ide_timer, jiffies + msecs_to_jiffies(10));
-+}
-+EXPORT_SYMBOL(ledtrig_sata_activity);
++    // Setup the PCI clock divider
++    {
++    static const u32 PCIDIV_MASK = (((1UL << SYS_CTRL_CKCTRL_CTRL_PCIDIV_NUM_BITS) - 1) << SYS_CTRL_CKCTRL_CTRL_PCIDIV_BIT);
++    *(volatile u32*)SYS_CTRL_CKCTRL_CTRL &= ~PCIDIV_MASK;
++    *(volatile u32*)SYS_CTRL_CKCTRL_CTRL |= (PCI_CLOCK_DIVIDER << SYS_CTRL_CKCTRL_CTRL_PCIDIV_BIT);
++    }
 +
-+static void ledtrig_ide_timerfunc(unsigned long data)
-+{
-+      if (ide_lastactivity != ide_activity) {
-+              ide_lastactivity = ide_activity;
-+              led_trigger_event(ledtrig_ide, LED_FULL);
-+              mod_timer(&ledtrig_ide_timer, jiffies + msecs_to_jiffies(10));
-+      } else {
-+              led_trigger_event(ledtrig_ide, LED_OFF);
-+      }
-+}
++    // Enable clock to PCI core
++    *(volatile u32*)SYS_CTRL_CKEN_SET_CTRL = (1UL << SYS_CTRL_CKEN_PCI_BIT);
 +
-+static int __init ledtrig_ide_init(void)
-+{
-+      led_trigger_register_simple("sata-disk", &ledtrig_ide);
-+      return 0;
-+}
++    // Enable auto-arbitration between static and PCI
++    *(u32*)SYS_CTRL_PCI_CTRL1 &= ~(1UL << SYSCTL_PCI_CTRL1_SYSPCI_STATIC_REQ);
 +
-+static void __exit ledtrig_ide_exit(void)
-+{
-+      led_trigger_unregister_simple(ledtrig_ide);
-+}
++    // Enable primary function on PCI clock line to be looped back
++    writel(readl(PCI_CLOCK_PRISEL_REG) | PCI_CLOCK_MASK, PCI_CLOCK_PRISEL_REG);
 +
-+module_init(ledtrig_ide_init);
-+module_exit(ledtrig_ide_exit);
++    // Enable GPIO output on PCI clock line to be looped back
++    writel(PCI_CLOCK_MASK, PCI_CLOCK_SET_OE_REG);
 +
-+MODULE_AUTHOR("John Larkworthy <john.larkworthy@hipox.com>");
-+MODULE_DESCRIPTION("LED SATA Disk Activity Trigger");
-+MODULE_LICENSE("GPL");
-diff -Nurd linux-2.6.24/arch/arm/mach-hipox/leon.c linux-2.6.24-oxe810/arch/arm/mach-hipox/leon.c
---- linux-2.6.24/arch/arm/mach-hipox/leon.c    1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mach-hipox/leon.c     2008-06-11 17:47:55.000000000 +0200
-@@ -0,0 +1,244 @@
-+/*
-+ * linux/arch/arm/mach-hipox/leon.c
-+ *
-+ * Copyright (C) 2005 Oxford Semiconductor Ltd
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+#ifdef CONFIG_SUPPORT_LEON
++#ifdef CONFIG_HIPOX_PCI_RESET
++    // Disable primary, secondary and teriary GPIO functions on PCI reset line
++    writel(readl(PCI_RESET_PRISEL_REG) & ~PCI_RESET_MASK, PCI_RESET_PRISEL_REG);
++    writel(readl(PCI_RESET_SECSEL_REG) & ~PCI_RESET_MASK, PCI_RESET_SECSEL_REG);
++    writel(readl(PCI_RESET_TERSEL_REG) & ~PCI_RESET_MASK, PCI_RESET_TERSEL_REG);
 +
-+#include <asm/io.h>
-+#include <asm/types.h>
-+#include <asm/arch/hardware.h>
-+#include <linux/ctype.h>
-+#include <linux/delay.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/errno.h>
-+#include <linux/init.h>
-+#include <linux/interrupt.h>
-+#include <linux/kernel.h>
-+#include <linux/slab.h>
-+#include <asm/arch/leon.h>
++    // Assert PCI reset from GPIO line
++    writel(PCI_RESET_MASK, PCI_RESET_OUTPUT_CLR_REG);
 +
-+static u8 asciihex_to_decimal(u8 ascii)
-+{
-+    return isdigit(ascii) ? (ascii - '0') : (isalpha(ascii) ? ((toupper(ascii) - 'A') + 10)  : 0);
-+}
++    // Enable GPIO output on PCI reset line
++    writel(PCI_RESET_MASK, PCI_RESET_SET_OE_REG);
 +
-+static u8 srec_read_u8(const s8** srec)
-+{
-+    u8 first_ascii  = **srec;
-+    u8 second_ascii = *++*srec;
-+    ++*srec;
-+    return ((asciihex_to_decimal(first_ascii) << 4) | asciihex_to_decimal(second_ascii));
-+}
++    // Wait awhile for PCI reset to take effect
++    mdelay(100);
 +
-+static u32 srec_read_u32(const s8** srec)
-+{
-+    u32 word  = ((u32)srec_read_u8(srec) << 24);
-+    word     |= ((u32)srec_read_u8(srec) << 16);
-+    word     |= ((u16)srec_read_u8(srec) << 8);
-+    word     |= srec_read_u8(srec);
-+    return word;
-+}
++    // Deassert PCI reset from GPIO line
++    writel(PCI_RESET_MASK, PCI_RESET_OUTPUT_SET_REG);
++#endif // CONFIG_HIPOX_PCI_RESET
++#endif // CONFIG_PCI
 +
-+static void skip_to_next_record(const s8** srec)
-+{
-+    while (*++*srec != '\n');
-+    ++*srec;
-+}
++#ifdef CONFIG_HIPOX_SATA_POWER_1
++    // Disable primary, secondary and teriary GPIO functions on SATA 1 power line
++    writel(readl(SATA_POWER_1_PRISEL_REG) & ~SATA_POWER_1_MASK, SATA_POWER_1_PRISEL_REG);
++    writel(readl(SATA_POWER_1_SECSEL_REG) & ~SATA_POWER_1_MASK, SATA_POWER_1_SECSEL_REG);
++    writel(readl(SATA_POWER_1_TERSEL_REG) & ~SATA_POWER_1_MASK, SATA_POWER_1_TERSEL_REG);
 +
-+/**
-+ * @param  srec An const s8** pointing to the position in the input s-record
-+ *         array at which to begin parsing
-+ * @param  buf An u8* into which any extracted record in to be placed
-+ * @param  adr An u8** into which either the extracted record's load address is
-+ *         to be written, or the execution start address
-+ * @param  len An u8* into which the length in bytes of the extracted record is
-+ *         to be written
-+ * @return An int which is zero if another record is available, else if non-zero
-+ *         indicated that the execution start address is available in the
-+ *         adr argument
-+ */
-+static void read_record(u8 len, const s8** srec, u8* buf)
-+{
-+    int quads = len/sizeof(u32);
-+    int spare = len - (quads*sizeof(u32));
++    // Enable power to SATA 1
++    writel(SATA_POWER_1_MASK, SATA_POWER_1_OUTPUT_SET_REG);
 +
-+    int i=0;
-+    while (i < quads) {
-+        ((u32*)buf)[i++] = srec_read_u32(srec);
-+    }
-+    i = len-spare;
-+    while (i < len) {
-+        buf[i++] = srec_read_u8(srec);
-+    }
-+}
++    // Enable GPIO output on SATA 1 power line
++    writel(SATA_POWER_1_MASK, SATA_POWER_1_SET_OE_REG);
++#endif // CONFIG_HIPOX_SATA_POWER_1
 +
-+static int get_next_record(const s8** srec, u8* buf, u8** adr, u8* len)
-+{
-+    int again;
-+    int last = 1;
++#ifdef CONFIG_HIPOX_SATA_POWER_2
++    // Disable primary, secondary and teriary GPIO functions on SATA 2 power line
++    writel(readl(SATA_POWER_2_PRISEL_REG) & ~SATA_POWER_2_MASK, SATA_POWER_2_PRISEL_REG);
++    writel(readl(SATA_POWER_2_SECSEL_REG) & ~SATA_POWER_2_MASK, SATA_POWER_2_SECSEL_REG);
++    writel(readl(SATA_POWER_2_TERSEL_REG) & ~SATA_POWER_2_MASK, SATA_POWER_2_TERSEL_REG);
 +
-+    *adr = 0;
-+    do {
-+        again = 0;
-+        if (**srec == 'S') {
-+            switch (*++*srec) {
-+                case '0':
-+                    skip_to_next_record(srec);
-+                    again = 1;
-+                    break;
-+                case '3':
-+                    ++*srec;
-+                    *len = srec_read_u8(srec) - sizeof(u32) - 1;
-+                    *adr = (u8*)srec_read_u32(srec);
-+                    read_record(*len, srec, buf);
-+                    skip_to_next_record(srec);
-+                    last = 0;
-+                    break;
-+                case '7':
-+                    ++*srec;
-+                    *len = srec_read_u8(srec) - 1;
-+                    if (*len >= sizeof(u32)) {
-+                        *adr = (u8*)srec_read_u32(srec);
-+                    }
-+                    break;
-+                default:
-+                    break;
-+            }
-+        }
-+    } while (again);
++    // Enable power to SATA 2
++    writel(SATA_POWER_2_MASK, SATA_POWER_2_OUTPUT_SET_REG);
 +
-+    return last;
-+}
++    // Enable GPIO output on SATA 2 power line
++    writel(SATA_POWER_2_MASK, SATA_POWER_2_SET_OE_REG);
++#endif // CONFIG_HIPOX_SATA_POWER_2
 +
-+static const u32 ENDIAN_LITTLE_READ_BIT = 30;
-+static const u32 ENDIAN_BIG_WRITE_BIT   = 31;
++#ifdef CONFIG_HIPOX_INSTRUMENT_COPIES_GPIO
++    // Use GPIO 6 (normally PCI Req 6) for copies instrumentation
++    #define INSTRUMENT_COPIES_GPIO_MASK ((1UL << 6) | (1UL << 7))
 +
-+static u8* convert_adr_to_virt(u8* adr)
-+{
-+      static const u32 ARM_HIGH_ORDER_ADR_BIT = 30;
++    // Enable normal GPIO on line
++    writel(readl(SYS_CTRL_GPIO_PRIMSEL_CTRL_0) & ~INSTRUMENT_COPIES_GPIO_MASK, SYS_CTRL_GPIO_PRIMSEL_CTRL_0);
++    writel(readl(SYS_CTRL_GPIO_SECSEL_CTRL_0)  & ~INSTRUMENT_COPIES_GPIO_MASK, SYS_CTRL_GPIO_SECSEL_CTRL_0);
++    writel(readl(SYS_CTRL_GPIO_TERTSEL_CTRL_0) & ~INSTRUMENT_COPIES_GPIO_MASK, SYS_CTRL_GPIO_TERTSEL_CTRL_0);
 +
-+    u32 virt = (u32)adr;
++    // Set line inactive to begin with
++    writel(INSTRUMENT_COPIES_GPIO_MASK, GPIO_A_OUTPUT_CLEAR);
 +
-+      // Zero the Leon endian control bits
-+      virt &= ~((1UL << ENDIAN_BIG_WRITE_BIT) | (1UL << ENDIAN_LITTLE_READ_BIT));
++    // Enable line as an output
++    writel(INSTRUMENT_COPIES_GPIO_MASK, GPIO_A_OUTPUT_ENABLE_SET);
++#endif // CONFIG_HIPOX_INSTRUMENT_COPIES_GPIO
 +
-+      // Convert to an ARM physical address
-+      virt |= (1UL << ARM_HIGH_ORDER_ADR_BIT);
++#ifdef CONFIG_HIPOX_USB_CKOUT
++    // Enable secondary function (USB clock out) on GPIO 10
++    writel(readl(SYS_CTRL_GPIO_PRIMSEL_CTRL_0) & ~(1UL << 10), SYS_CTRL_GPIO_PRIMSEL_CTRL_0);
++    writel(readl(SYS_CTRL_GPIO_SECSEL_CTRL_0)  |  (1UL << 10), SYS_CTRL_GPIO_SECSEL_CTRL_0);
++#endif // CONFIG_HIPOX_USB_CKOUT
 +
-+    // Is address sane?
-+    if (virt < LEON_IMAGE_BASE_PA) {
-+        panic("CoPro SRAM load address 0x%08x below mapped region beginning at 0x%08lx\n", (u32)adr, LEON_IMAGE_BASE_PA);
-+    } else {
-+        virt -= LEON_IMAGE_BASE_PA;
-+        virt += LEON_IMAGE_BASE;
-+    }
++#ifdef CONFIG_HIPOX_USB_HUB_RESET_CONTROL
++    // Disable primary, secondary and teriary GPIO functions on USB hub reset control line
++    writel(readl(USB_HUB_RESET_PRISEL_REG) & ~USB_HUB_RESET_MASK, USB_HUB_RESET_PRISEL_REG);
++    writel(readl(USB_HUB_RESET_SECSEL_REG) & ~USB_HUB_RESET_MASK, USB_HUB_RESET_SECSEL_REG);
++    writel(readl(USB_HUB_RESET_TERSEL_REG) & ~USB_HUB_RESET_MASK, USB_HUB_RESET_TERSEL_REG);
 +
-+    return (u8*)virt;
-+}
++#ifdef CONFIG_HIPOX_USB_HUB_RESET_TOGGLE
++      // Assert USB hub reset
++      writel(USB_HUB_RESET_MASK, CONFIG_HIPOX_USB_HUB_RESET_ACTIVE_HIGH ? USB_HUB_RESET_OUTPUT_SET_REG : USB_HUB_RESET_OUTPUT_CLR_REG);
++#else
++      // Deassert USB hub reset
++      writel(USB_HUB_RESET_MASK, CONFIG_HIPOX_USB_HUB_RESET_ACTIVE_HIGH ? USB_HUB_RESET_OUTPUT_CLR_REG : USB_HUB_RESET_OUTPUT_SET_REG);
++#endif // CONFIG_HIPOX_USB_HUB_RESET_TOGGLE
 +
-+static void leon_load_image(const s8 *srec)
-+{
-+    u8       *buf;
-+    u8       *adr;
-+    u8        len;
-+    u32       code_base;
++    // Enable GPIO output on USB hub reset line
++    writel(USB_HUB_RESET_MASK, USB_HUB_RESET_SET_OE_REG);
 +
-+    // Copy each record to the specified address
-+    // Convert the LEON physical address to an ARM virtual address before
-+      // attempting to get the ARM to access it
-+    // NB must endian-swap any trailing non-quad multiple bytes, as LEON will
-+    // expect its instruction data in big endian format, whereas the ARM is
-+    // little endian
-+    buf  = kmalloc(512, GFP_KERNEL);
-+    while (!get_next_record(&srec, buf, &adr, &len)) {
-+        int i=0;
-+        int quads = len/sizeof(u32);
-+        int spare = len - (quads*sizeof(u32));
-+        int padded_len = len+(sizeof(u32)-spare);
-+        u32* quad_ptr;
++#ifdef CONFIG_HIPOX_USB_HUB_RESET_TOGGLE
++      if (CONFIG_HIPOX_USB_HUB_RESET_PERIOD_MS > 0) {
++              // Wait for USB hub reset toggle assertion time
++              mdelay(CONFIG_HIPOX_USB_HUB_RESET_PERIOD_MS);
++      }
 +
-+        adr = convert_adr_to_virt(adr);
++      // Deassert USB hub reset
++      writel(USB_HUB_RESET_MASK, CONFIG_HIPOX_USB_HUB_RESET_ACTIVE_HIGH ? USB_HUB_RESET_OUTPUT_CLR_REG : USB_HUB_RESET_OUTPUT_SET_REG);
++#endif // CONFIG_HIPOX_USB_HUB_RESET_TOGGLE
 +
-+        quad_ptr = (u32*)adr;
-+        while (i < quads) {
-+            *quad_ptr++ = ((u32*)buf)[i++];
-+        }
-+        adr = (u8*)quad_ptr;
-+        for (i=len; i < padded_len; i++) {
-+            buf[i] = 0;
-+        }
-+        i = padded_len-1;
-+        while (i >= (len-spare)) {
-+            *adr++ = buf[i--];
-+        }
-+    }
-+    kfree(buf);
++#endif // CONFIG_HIPOX_USB_HUB_RESET_CONTROL
++}
 +
-+    // Start LEON execution at the address specified by the S-records, with
-+    // correct endianess. Use the address unchanged, as the LEON required
-+    // physical addresses and may make use of alternative upper nibble values
-+    code_base = (((u32)adr & ~((1UL << ENDIAN_BIG_WRITE_BIT) | (1UL << ENDIAN_LITTLE_READ_BIT))) | (1UL << ENDIAN_BIG_WRITE_BIT));
++static void __init hipox_fixup(
++    struct machine_desc *desc,
++    struct tag *tags,
++    char **cmdline,
++    struct meminfo *mi)
++{
 +
-+    // Set the LEON's start address
-+    printk(KERN_NOTICE "CoPro: Programming start address as 0x%08x (basic adr = 0x%08x)\n", code_base, (u32)adr);
-+    writel(code_base, SYS_CTRL_COPRO_CTRL);
++    mi->nr_banks = 0;
++    mi->bank[mi->nr_banks].start = SDRAM_PA;
++    mi->bank[mi->nr_banks].size  = SDRAM_SIZE;
++    mi->bank[mi->nr_banks].node = mi->nr_banks;
++    ++mi->nr_banks;
++#ifdef CONFIG_DISCONTIGMEM
++    mi->bank[mi->nr_banks].start = SRAM_PA;
++    mi->bank[mi->nr_banks].size  = SRAM_SIZE;
++#ifdef LEON_IMAGE_IN_SRAM
++    mi->bank[mi->nr_banks].size -= LEON_IMAGE_SIZE;
++#endif
++    mi->bank[mi->nr_banks].node = mi->nr_banks;
++    ++mi->nr_banks;
++#endif
 +
-+    // Ensure start address has been loaded before release the LEON from reset
-+    wmb();
++//printk(KERN_NOTICE "%d memory %s\n", mi->nr_banks, (mi->nr_banks > 1) ? "regions" : "region");
 +}
 +
-+void init_copro(const s8 *srec, unsigned long arg)
++#ifdef CONFIG_DO_MEM_TEST
++static void __init hipox_asm_copy(void* dst, void* src, u32 length)
 +{
-+    // Ensure the LEON is in reset
-+    writel(1UL << SYS_CTRL_RSTEN_COPRO_BIT, SYS_CTRL_RSTEN_SET_CTRL);
++    // Assume the length is consistent with transfering 8 quads per load/store
++    asm volatile(
++        "1:ldmia %0!, {r3, r4, r5, r6, r7, r8, r9, r12};"
++        "subs %2, %2, #32;"
++        "stmia %1!, {r3, r4, r5, r6, r7, r8, r9, r12};"
++        "bne 1b;"
++        :
++        : "r" (src), "r" (dst), "r" (length)
++        : "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r12");
++}
 +
-+    // Enable the clock to the LEON
-+    writel(1UL << SYS_CTRL_CKEN_COPRO_BIT, SYS_CTRL_CKEN_SET_CTRL);
++static void __init hipox_mem_test(void)
++{
++    static const unsigned BUFFER_SIZE_CHARS = 16*1024;
++    static const unsigned BUFFER_ELEMENTS = (BUFFER_SIZE_CHARS / sizeof(unsigned long));
 +
-+    // Ensure reset and clock operations are complete
-+    wmb();
++    dma_addr_t dma_address;
++    unsigned long* buffer;
 +
-+    // Place LEON context argument in top quad of SRAM
-+      *((u32*)(LEON_IMAGE_BASE+LEON_IMAGE_SIZE-sizeof(u32))) = arg;
++    buffer = dma_alloc_coherent(0, BUFFER_SIZE_CHARS, &dma_address, GFP_KERNEL | GFP_DMA);
++    if (!buffer) {
++        printk(KERN_ERR "$RFailed to allocate ucached/unbuffered memory test buffer\n");
++    } else {
++        static const int ITERATIONS = 10;
 +
-+    // Load LEON's program and data and execution start address
-+    leon_load_image(srec);
++        unsigned long* buf1 = buffer;
++        unsigned long* buf2 = buffer + (BUFFER_ELEMENTS/2);
++        int j;
++        u32* time1 = (u32*)kmalloc(ITERATIONS *sizeof(u32), GFP_KERNEL);
++        u32* time2 = (u32*)kmalloc(ITERATIONS *sizeof(u32), GFP_KERNEL);
 +
-+    // Release the LEON from reset so it begins execution of the loaded code
-+    writel(1UL << SYS_CTRL_RSTEN_COPRO_BIT, SYS_CTRL_RSTEN_CLR_CTRL);
++        BUG_ON(!time1 || !time2);
++        
++        printk("Uncached/unbuffered: src = 0x%08x, dst = 0x%08x, length = %u, elements = %u, dma_address = 0x%08x\n", (u32)buf1, (u32)buf2, BUFFER_SIZE_CHARS/2, BUFFER_ELEMENTS/2, dma_address);
 +
-+    // Give the LEON a chance to stabilise before giving it any commands
-+    mdelay(100);
-+    return;
-+}
-+EXPORT_SYMBOL_GPL(init_copro);
++        printk("\nAll accesses:\n");
++        init_ahb_monitors(AHB_MON_HWRITE_READS_AND_WRITES, 0, 0, 0, 0);
 +
-+void shutdown_copro(void)
-+{
-+    // Ensure the LEON is in reset
-+    writel(1UL << SYS_CTRL_RSTEN_COPRO_BIT, SYS_CTRL_RSTEN_SET_CTRL);
++        for (j=0; j < ITERATIONS; j++) {
++            unsigned long* src = buf1;
++            unsigned long* dst = buf2;
++//            int i;
 +
-+    // Disable the clock to the LEON
-+    writel(1UL << SYS_CTRL_CKEN_COPRO_BIT, SYS_CTRL_CKEN_CLR_CTRL);
++            time1[j] = readl(TIMER2_VALUE);
++//            memcpy(dst, src, BUFFER_SIZE_CHARS/2);
++            hipox_asm_copy(dst, src, BUFFER_SIZE_CHARS/2);
++//            for (i=0; i<BUFFER_ELEMENTS/2; i++) {
++//                *dst++ = *src++;
++//            }
++            time2[j] = readl(TIMER2_VALUE);
++        }
++        read_ahb_monitors();
++        for (j=0; j < ITERATIONS; j++) {
++            printk("%u->%lu Bytes/s\n", time1[j]-time2[j], 100000UL * (BUFFER_SIZE_CHARS/2) / (time1[j]-time2[j]));
++        }
 +
-+    // Ensure reset and clock operations are complete
-+    wmb();
-+}
-+EXPORT_SYMBOL_GPL(shutdown_copro);
++        printk("\nNon-burst accesses:\n");
++        init_ahb_monitors(AHB_MON_HWRITE_READS_AND_WRITES, ~0, AHB_MON_HBURST_SINGLE, 0, 0);
++        for (j=0; j < ITERATIONS; j++) {
++            unsigned long* src = buf1;
++            unsigned long* dst = buf2;
++//            int i;
 +
-+#endif // CONFIG_SUPPORT_LEON
-diff -Nurd linux-2.6.24/arch/arm/mach-hipox/hipox-ahb-monitor.c linux-2.6.24-oxe810/arch/arm/mach-hipox/hipox-ahb-monitor.c
---- linux-2.6.24/arch/arm/mach-hipox/hipox-ahb-monitor.c       1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mach-hipox/hipox-ahb-monitor.c        2008-06-11 17:47:55.000000000 +0200
-@@ -0,0 +1,374 @@
-+/*
-+ *  arch/arm/mach-hipox/hipox-ahb-monitor.c
-+ *
-+ *  Copyright (C) 2006 Oxford Semiconductor Ltd
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ *
-+ */
++            time1[j] = readl(TIMER2_VALUE);
++//            memcpy(dst, src, BUFFER_SIZE_CHARS/2);
++            hipox_asm_copy(dst, src, BUFFER_SIZE_CHARS/2);
++//            for (i=0; i<BUFFER_ELEMENTS/2; i++) {
++//                *dst++ = *src++;
++//            }
++            time2[j] = readl(TIMER2_VALUE);
++        }
++        read_ahb_monitors();
++        for (j=0; j < ITERATIONS; j++) {
++            printk("%u->%lu Bytes/s\n", time1[j]-time2[j], 100000UL * (BUFFER_SIZE_CHARS/2) / (time1[j]-time2[j]));
++        }
 +
-+#include <linux/types.h>
-+#include <linux/module.h>
-+#include <linux/errno.h>
-+#include <linux/miscdevice.h>
-+#include <linux/smp_lock.h>
-+#include <linux/kernel.h>
-+#include <linux/delay.h>
-+#include <linux/sched.h>
-+#include <linux/i2c.h>
-+#include <linux/proc_fs.h>
-+#include <linux/capability.h>
-+#include <linux/slab.h>
-+#include <linux/init.h>
-+#include <linux/spinlock.h>
-+#include <linux/smp_lock.h>
-+#include <linux/wait.h>
-+#include <linux/suspend.h>
-+#include <linux/kthread.h>
-+#include <linux/moduleparam.h>
++        printk("\nINCR accesses:\n");
++        init_ahb_monitors(AHB_MON_HWRITE_READS_AND_WRITES, ~0, AHB_MON_HBURST_INCR, 0, 0);
++        for (j=0; j < ITERATIONS; j++) {
++            unsigned long* src = buf1;
++            unsigned long* dst = buf2;
++//            int i;
 +
-+#include <asm/io.h>
-+#include <asm/system.h>
-+#include <asm/sections.h>
-+#include <asm/uaccess.h>
-+#include <asm/bitops.h>
++            time1[j] = readl(TIMER2_VALUE);
++//            memcpy(dst, src, BUFFER_SIZE_CHARS/2);
++            hipox_asm_copy(dst, src, BUFFER_SIZE_CHARS/2);
++//            for (i=0; i<BUFFER_ELEMENTS/2; i++) {
++//                *dst++ = *src++;
++//            }
++            time2[j] = readl(TIMER2_VALUE);
++        }
++        read_ahb_monitors();
++        for (j=0; j < ITERATIONS; j++) {
++            printk("%u->%lu Bytes/s\n", time1[j]-time2[j], 100000UL * (BUFFER_SIZE_CHARS/2) / (time1[j]-time2[j]));
++        }
 +
-+#include <asm/hardware.h>
++        printk("\nWRAP4 accesses:\n");
++        init_ahb_monitors(AHB_MON_HWRITE_READS_AND_WRITES, ~0, AHB_MON_HBURST_WRAP4, 0, 0);
++        for (j=0; j < ITERATIONS; j++) {
++            unsigned long* src = buf1;
++            unsigned long* dst = buf2;
++//            int i;
 +
++            time1[j] = readl(TIMER2_VALUE);
++//            memcpy(dst, src, BUFFER_SIZE_CHARS/2);
++            hipox_asm_copy(dst, src, BUFFER_SIZE_CHARS/2);
++//            for (i=0; i<BUFFER_ELEMENTS/2; i++) {
++//                *dst++ = *src++;
++//            }
++            time2[j] = readl(TIMER2_VALUE);
++        }
++        read_ahb_monitors();
++        for (j=0; j < ITERATIONS; j++) {
++            printk("%u->%lu Bytes/s\n", time1[j]-time2[j], 100000UL * (BUFFER_SIZE_CHARS/2) / (time1[j]-time2[j]));
++        }
 +
-+/* usb test masks and offsets */
-+#define TEST_MASK    0xF
-+#define TEST_OFFSET  16
++        printk("\nINCR4 accesses:\n");
++        init_ahb_monitors(AHB_MON_HWRITE_READS_AND_WRITES, ~0, AHB_MON_HBURST_INCR4, 0, 0);
++        for (j=0; j < ITERATIONS; j++) {
++            unsigned long* src = buf1;
++            unsigned long* dst = buf2;
++//            int i;
 +
-+#define MODULE_VERS "0.1"
-+#define MODULE_NAME "hipox-test"
-+MODULE_AUTHOR(                "John Larkworthy"                                       );
-+MODULE_DESCRIPTION(   "Driver to access the test hardware in hipox units"     );
-+MODULE_LICENSE(               "GPL"                                                   );
++            time1[j] = readl(TIMER2_VALUE);
++//            memcpy(dst, src, BUFFER_SIZE_CHARS/2);
++            hipox_asm_copy(dst, src, BUFFER_SIZE_CHARS/2);
++//            for (i=0; i<BUFFER_ELEMENTS/2; i++) {
++//                *dst++ = *src++;
++//            }
++            time2[j] = readl(TIMER2_VALUE);
++        }
++        read_ahb_monitors();
++        for (j=0; j < ITERATIONS; j++) {
++            printk("%u->%lu Bytes/s\n", time1[j]-time2[j], 100000UL * (BUFFER_SIZE_CHARS/2) / (time1[j]-time2[j]));
++        }
++
++        printk("\nWRAP8 accesses:\n");
++        init_ahb_monitors(AHB_MON_HWRITE_READS_AND_WRITES, ~0, AHB_MON_HBURST_WRAP8, 0, 0);
++        for (j=0; j < ITERATIONS; j++) {
++            unsigned long* src = buf1;
++            unsigned long* dst = buf2;
++//            int i;
 +
++            time1[j] = readl(TIMER2_VALUE);
++//            memcpy(dst, src, BUFFER_SIZE_CHARS/2);
++            hipox_asm_copy(dst, src, BUFFER_SIZE_CHARS/2);
++//            for (i=0; i<BUFFER_ELEMENTS/2; i++) {
++//                *dst++ = *src++;
++//            }
++            time2[j] = readl(TIMER2_VALUE);
++        }
++        read_ahb_monitors();
++        for (j=0; j < ITERATIONS; j++) {
++            printk("%u->%lu Bytes/s\n", time1[j]-time2[j], 100000UL * (BUFFER_SIZE_CHARS/2) / (time1[j]-time2[j]));
++        }
 +
-+static struct proc_dir_entry *proc_dir_usb_test_read, *hipox_test_dir;
++        printk("\nINCR8 accesses:\n");
++        init_ahb_monitors(AHB_MON_HWRITE_READS_AND_WRITES, ~0, AHB_MON_HBURST_INCR8, 0, 0);
++        for (j=0; j < ITERATIONS; j++) {
++            unsigned long* src = buf1;
++            unsigned long* dst = buf2;
++//            int i;
 +
++            time1[j] = readl(TIMER2_VALUE);
++//            memcpy(dst, src, BUFFER_SIZE_CHARS/2);
++            hipox_asm_copy(dst, src, BUFFER_SIZE_CHARS/2);
++//            for (i=0; i<BUFFER_ELEMENTS/2; i++) {
++//                *dst++ = *src++;
++//            }
++            time2[j] = readl(TIMER2_VALUE);
++        }
++        read_ahb_monitors();
++        for (j=0; j < ITERATIONS; j++) {
++            printk("%u->%lu Bytes/s\n", time1[j]-time2[j], 100000UL * (BUFFER_SIZE_CHARS/2) / (time1[j]-time2[j]));
++        }
 +
-+static struct {
-+      void * address;
-+      char * name;
-+      long unsigned low_add;
-+      long unsigned high_add;
-+      unsigned burst;
-+      unsigned burst_mask;
-+      unsigned hprot;
-+      unsigned hprot_mask;
-+      unsigned mode;
-+} monitor[] =
-+{
-+      { (void *) 0x00000, "ARM_Data", 0, 0xFFFFFFFFl, 0, 0, 0, 0, 0 },
-+      { (void *) 0x10000, "Arm_Inst", 0, 0xFFFFFFFFl, 0, 0, 0, 0, 0 },
-+      { (void *) 0x20000, "DMA_A", 0, 0xFFFFFFFFl, 0, 0, 0, 0, 0 },
-+      { (void *) 0x30000, "DMA_B", 0, 0xFFFFFFFFl, 0, 0, 0, 0, 0 },
-+      { (void *) 0x40000, "CoPro", 0, 0xFFFFFFFFl, 0, 0, 0, 0, 0 },
-+      { (void *) 0x50000, "USBHS", 0, 0xFFFFFFFFl, 0, 0, 0, 0, 0 },
-+      { (void *) 0x60000, "GMAC", 0, 0xFFFFFFFFl, 0, 0, 0, 0, 0 },
-+      { (void *) 0x70000, "PCI", 0, 0xFFFFFFFFl, 0, 0, 0, 0, 0 }
-+};            
-+#define NO_MONITORS (sizeof(monitor)/sizeof(monitor[0]))
++        printk("\nWRAP16 accesses:\n");
++        init_ahb_monitors(AHB_MON_HWRITE_READS_AND_WRITES, ~0, AHB_MON_HBURST_WRAP16, 0, 0);
++        for (j=0; j < ITERATIONS; j++) {
++            unsigned long* src = buf1;
++            unsigned long* dst = buf2;
++//            int i;
 +
-+/* create proc filing system entries to accept configuration data */
-+static int usb_test_write_entries(const char *name, write_proc_t *w, read_proc_t *r, int data)
-+{
-+      struct proc_dir_entry * entry = create_proc_entry(name, 0222, hipox_test_dir);
-+      if (entry) {
-+              entry->write_proc = w;
-+              entry->read_proc =r;
-+              entry->data = (void *)data;
-+              entry->owner = THIS_MODULE;
-+              return 0;
-+      }
-+      else
-+      {
-+              return -ENOMEM;
-+      }
-+}
++            time1[j] = readl(TIMER2_VALUE);
++//            memcpy(dst, src, BUFFER_SIZE_CHARS/2);
++            hipox_asm_copy(dst, src, BUFFER_SIZE_CHARS/2);
++//            for (i=0; i<BUFFER_ELEMENTS/2; i++) {
++//                *dst++ = *src++;
++//            }
++            time2[j] = readl(TIMER2_VALUE);
++        }
++        read_ahb_monitors();
++        for (j=0; j < ITERATIONS; j++) {
++            printk("%u->%lu Bytes/s\n", time1[j]-time2[j], 100000UL * (BUFFER_SIZE_CHARS/2) / (time1[j]-time2[j]));
++        }
 +
-+static int
-+hipox_test_read(char *buf, char **start, off_t offset,
-+                int count, int *eof, void *unused)
-+{
-+      
-+      int i;
-+      int len = 0;
-+      long unsigned *rd_monitor;
-+      
-+      
-+      for (i=0; i < NO_MONITORS; i++)
-+      {
-+      rd_monitor = (long unsigned *) (AHB_MON_BASE + monitor[i].address);
-+              len += sprintf(buf+len, "%s     CL:%ld EV:%ld hld:%ld slw:%lx tm:%ld\n", 
-+                      monitor[i].name, 
-+                      *rd_monitor, 
-+                      *(rd_monitor+1),
-+                      *(rd_monitor+2),
-+                      *(rd_monitor+3),
-+                      (*(rd_monitor+4) & 0xFFFF));
-+      }
-+      *eof=1;
-+      return len;
-+}
-+/*
-+ * function to clear and start all the timers mainly together.
-+ */
-+#define MAX_CMD 5
-+static int
-+hipox_test_control(struct file *file, const char *buf, unsigned long count, void * data)
-+{
-+      int len;
-+      int i;
-+      long unsigned *rd_monitor;
-+      unsigned cmd = 0;
-+      
-+      char local[MAX_CMD];
-+      int result;
++        printk("\nINCR16 accesses:\n");
++        init_ahb_monitors(AHB_MON_HWRITE_READS_AND_WRITES, ~0, AHB_MON_HBURST_INCR16, 0, 0);
++        for (j=0; j < ITERATIONS; j++) {
++            unsigned long* src = buf1;
++            unsigned long* dst = buf2;
++//            int i;
 +
-+      if (count > MAX_CMD-1)
-+              len= MAX_CMD-1;
-+      else 
-+              len=count;
-+              
-+      if (copy_from_user(&local, buf, len))
-+              return -EFAULT;
-+      
-+      result=sscanf(local, "%d", &cmd);
-+      
-+      switch (cmd) 
-+      {
-+              case 0: 
-+                      printk(KERN_INFO "hipox-test: stop command\n");
-+                      break;
-+              case 1:
-+                      printk(KERN_INFO "hipox-test: run command\n");
-+                      break;
-+              case 2:
-+                      printk(KERN_INFO "hipox-test: reset command\n");
-+                      break;
-+              default:
-+                      printk(KERN_INFO "hipox-test: ignored command\n");
-+                      return len;
-+                      break;
-+      }
-+      
-+      for (i=0; i < NO_MONITORS; i++)
-+      {
-+              rd_monitor = (long unsigned *) (AHB_MON_BASE + monitor[i].address);
-+              *rd_monitor = (long unsigned) cmd;
-+      }
-+      return len;
-+}
++            time1[j] = readl(TIMER2_VALUE);
++//            memcpy(dst, src, BUFFER_SIZE_CHARS/2);
++            hipox_asm_copy(dst, src, BUFFER_SIZE_CHARS/2);
++//            for (i=0; i<BUFFER_ELEMENTS/2; i++) {
++//                *dst++ = *src++;
++//            }
++            time2[j] = readl(TIMER2_VALUE);
++        }
++        read_ahb_monitors();
++        for (j=0; j < ITERATIONS; j++) {
++            printk("%u->%lu Bytes/s\n", time1[j]-time2[j], 100000UL * (BUFFER_SIZE_CHARS/2) / (time1[j]-time2[j]));
++        }
 +
++        dma_free_coherent(0, BUFFER_SIZE_CHARS, buffer, dma_address);
 +
-+/*
-+ * The write function accepts a line as below:
-+ * start_addr, end_addr, mode, burst, burst_mask, hprot, hprot_mask 
-+ * expected string length is 10 + 10 + 3 + 3 + 4 + 3 + 4 < 40char.
-+ * This is decoded by the scanf function into the separate items. - missing items are defaulted.
-+ */
-+ 
-+#define MAX_STRING 40
-+static int
-+hipox_test_config_write(struct file *file, const char *buf, unsigned long count, void * data)
-+{
-+      
-+      int len;        
-+      int i = (int) data;
-+      char local[MAX_STRING];
-+      int result;
-+      unsigned long * mon_ptr;
++        kfree(time1);
++        kfree(time2);
++    }
 +
-+      if (count > MAX_STRING-1)
-+              len= MAX_STRING-1;
-+      else 
-+              len=count;
-+              
-+      if (copy_from_user(&local, buf, len))
-+              return -EFAULT;
-+      
-+      /* extract value from buffer and store */
-+      
-+      result = sscanf(local, "%li,%li,%i,%i,%i,%i,%i", 
-+              &monitor[i].low_add, 
-+              &monitor[i].high_add, 
-+              &monitor[i].mode, 
-+              &monitor[i].burst, 
-+              &monitor[i].burst_mask, 
-+              &monitor[i].hprot,
-+              &monitor[i].hprot_mask
-+      );
-+      if (result != 7)
-+              return -EINVAL;
-+              
-+      /* load values on hardware */
-+      
-+      mon_ptr=(unsigned long *) (AHB_MON_BASE + monitor[i].address);
++    buffer = kmalloc(BUFFER_SIZE_CHARS, GFP_KERNEL | GFP_DMA);
++    if (!buffer) {
++        printk(KERN_ERR "$RFailed to allocate cached memory test buffer\n");
++    } else {
++        static const int ITERATIONS = 100;
 +
-+      *(mon_ptr + 1) = monitor[i].mode & 0x3;
-+      *(mon_ptr + 2) = monitor[i].low_add;
-+      *(mon_ptr + 3) = monitor[i].high_add;
-+      *(mon_ptr + 4) = ((monitor[i].burst & 0x7) << 4 | (monitor[i].burst_mask & 0x7));
-+      *(mon_ptr + 5) = ((monitor[i].hprot & 0xf) << 4 | (monitor[i].hprot_mask &0xf));
-+              
-+      return len;
-+}
++        unsigned long* buf1 = buffer;
++        unsigned long* buf2 = buffer + (BUFFER_ELEMENTS/2);
++        unsigned long* src = buf1;
++        unsigned long* dst = buf2;
++        int j;
++        u32* time1 = (u32*)kmalloc(ITERATIONS *sizeof(u32), GFP_KERNEL);
++        u32* time2 = (u32*)kmalloc(ITERATIONS *sizeof(u32), GFP_KERNEL);
 +
-+static int
-+hipox_test_config_read(char *buf, char **start, off_t offset,
-+                int count, int *eof, void *data)
-+{
-+      
-+      int len = 0;    
-+      int i = (int) data;
-+      
-+      len += sprintf(buf+len, "name low  high  mode burst/mask hprot/mask\n"); 
++        BUG_ON(!time1 || !time2);
 +
-+      len += sprintf(buf+len, "%s     0x%08lx 0x%08lx %d 0x%x/0x%x 0x%x/0x%x\n", 
-+              monitor[i].name, 
-+              monitor[i].low_add, 
-+              monitor[i].high_add, 
-+              monitor[i].mode, 
-+              monitor[i].burst, 
-+              monitor[i].burst_mask, 
-+              monitor[i].hprot,
-+              monitor[i].hprot_mask);
-+              
-+              
-+      *eof=1;
-+      return len;
-+}
++        printk("Cached/: src = 0x%08x, dst = 0x%08x, length = %u, elements = %u\n", (u32)buf1, (u32)buf2, BUFFER_SIZE_CHARS/2, BUFFER_ELEMENTS/2);
 +
-+static int __init hipox_test_init(void)
-+{
-+      int rv=0;
-+      int i;
-+      
-+      hipox_test_dir = proc_mkdir(MODULE_NAME, NULL);
-+      if (hipox_test_dir == NULL) {
-+              printk(KERN_ERR "hipox-test: unable to register /proc/usb-test\n");
-+              rv= -ENOMEM;
-+              goto out;
-+      }
-+      
-+      hipox_test_dir->owner= THIS_MODULE;
-+      
-+      proc_dir_usb_test_read = create_proc_entry("read", 0444, hipox_test_dir);
-+      if (proc_dir_usb_test_read) {
-+              proc_dir_usb_test_read->read_proc = hipox_test_read;
-+      } else {
-+              printk(KERN_ERR "hipox-test: unable to register /proc/usb-test/read\n");
-+              rv = -ENOMEM;
-+              goto no_read;
-+      }
++        init_ahb_monitors(AHB_MON_HWRITE_READS_AND_WRITES, 0, 0, 0, 0);
 +
-+      /* create port write file entries */
-+      for (i=0;i<NO_MONITORS;i++) 
-+      {
-+              rv = usb_test_write_entries(monitor[i].name, &hipox_test_config_write, &hipox_test_config_read, i);
-+              if (rv < 0)
-+              {
-+                      while (i != 0)
-+                      {
-+                              i--;
-+                              /* remove any allocated entries */
-+                              remove_proc_entry (monitor[i].name, hipox_test_dir);
-+                      } 
-+                      goto no_write;
-+              }
-+      }
++        // Measure the first cached iteration separately
++        printk("1st iteration:\n");
++        restart_ahb_monitors();
++        time1[0] = readl(TIMER2_VALUE);
++//            memcpy(dst, src, BUFFER_SIZE_CHARS/2);
++        hipox_asm_copy(dst, src, BUFFER_SIZE_CHARS/2);
++//            for (i=0; i<BUFFER_ELEMENTS/2; i++) {
++//                *dst++ = *src++;
++//            }
++        time2[0] = readl(TIMER2_VALUE);
++        read_ahb_monitors();
++        printk("%u->%lu Bytes/s\n", time1[0]-time2[0], 100000UL * (BUFFER_SIZE_CHARS/2) / (time1[0]-time2[0]));
 +
-+      {
-+              struct proc_dir_entry * entry = create_proc_entry("control", 0666, hipox_test_dir);
-+              if (entry) {
-+                      entry->write_proc = hipox_test_control;
-+                      entry->owner = THIS_MODULE;
-+                      return 0;
-+              }
-+              else
-+              {
-+                      goto no_control;
-+              }
-+      }
++        printk("Subsequent iterations:\n");
++        restart_ahb_monitors();
++        for (j=1; j < ITERATIONS; j++) {
++            src = buf1;
++            dst = buf2;
++//            int i;
 +
++            time1[j] = readl(TIMER2_VALUE);
++//            memcpy(dst, src, BUFFER_SIZE_CHARS/2);
++            hipox_asm_copy(dst, src, BUFFER_SIZE_CHARS/2);
++//            for (i=0; i<BUFFER_ELEMENTS/2; i++) {
++//                *dst++ = *src++;
++//            }
++            time2[j] = readl(TIMER2_VALUE);
++        }
++        read_ahb_monitors();
 +
-+      printk(KERN_INFO "%s %s initialised\n", MODULE_NAME, MODULE_VERS);
++        for (j=1; j < ITERATIONS; j++) {
++            printk("%u->%lu Bytes/s\n", time1[j]-time2[j], 100000UL * (BUFFER_SIZE_CHARS/2) / (time1[j]-time2[j]));
++        }
 +
-+      return 0;
++        kfree(time1);
++        kfree(time2);
 +
-+      no_control:
-+              for (i = NO_MONITORS; i != 0; )
-+              {
-+                      i--;
-+                      /* remove any allocated entries */
-+                      remove_proc_entry (monitor[i].name, hipox_test_dir);
-+              } 
-+      
-+      no_write:
-+              remove_proc_entry("read", hipox_test_dir);
-+      no_read:
-+              remove_proc_entry(MODULE_NAME, NULL);
-+      out:
-+              return rv;
++        kfree(buffer);
++    }
 +}
++#endif // CONFIG_DO_MEM_TEST
 +
++#ifdef CONFIG_HIPOX_LED_TEST
 +
-+static void __exit hipox_test_exit(void)
-+{
-+      int i;
-+      
-+      remove_proc_entry("control", hipox_test_dir);
-+      
-+      for (i = 0; i < NO_MONITORS; i++)
-+      {
-+              remove_proc_entry(monitor[i].name, hipox_test_dir);
-+      }
-+      
-+      remove_proc_entry("read", hipox_test_dir);
-+      remove_proc_entry(MODULE_NAME, NULL);
-+
-+      printk(KERN_INFO "%s %s removed\n", MODULE_NAME, MODULE_VERS);
-+      
-+}
++#define LED_D1  (1UL << 6)
++#define LED_D2  (1UL << 7)
++#define LED_D3  (1UL << 13)
++#define LED_D4  (1UL << 14)
++#define LED_D5  (1UL << 19)
++#define LED_D6  (1UL << 21)
++#define LED_D7  (1UL << 25)
++#define LED_D8  (1UL << 26)
++#define LED_D9  (1UL << 27)
++#define FIRST_LEDS_MASK (LED_D1 | LED_D2 | LED_D3 | LED_D4 | LED_D5 | LED_D6 | LED_D7 | LED_D8 | LED_D9)
 +
++#define LED_D10 (1UL << 1)
++#define SECOND_LEDS_MASK (LED_D10)
 +
-+module_init(hipox_test_init);
-+module_exit(hipox_test_exit);
++#define PWM_MASK (1UL << 8)
 +
++static void test_leds_and_pwm(void)
++{
++    // Disable primary, secondary and teriary GPIO functions for first nine LEDS
++    writel(readl(SYS_CTRL_GPIO_PRIMSEL_CTRL_0) & ~FIRST_LEDS_MASK, SYS_CTRL_GPIO_PRIMSEL_CTRL_0);
++    writel(readl(SYS_CTRL_GPIO_SECSEL_CTRL_0)  & ~FIRST_LEDS_MASK, SYS_CTRL_GPIO_SECSEL_CTRL_0);
++    writel(readl(SYS_CTRL_GPIO_TERTSEL_CTRL_0) & ~FIRST_LEDS_MASK, SYS_CTRL_GPIO_TERTSEL_CTRL_0);
 +
++    // Disable primary, secondary and teriary GPIO functions for last LED
++    writel(readl(SYS_CTRL_GPIO_PRIMSEL_CTRL_1) & ~SECOND_LEDS_MASK, SYS_CTRL_GPIO_PRIMSEL_CTRL_1);
++    writel(readl(SYS_CTRL_GPIO_SECSEL_CTRL_1)  & ~SECOND_LEDS_MASK, SYS_CTRL_GPIO_SECSEL_CTRL_1);
++    writel(readl(SYS_CTRL_GPIO_TERTSEL_CTRL_1) & ~SECOND_LEDS_MASK, SYS_CTRL_GPIO_TERTSEL_CTRL_1);
 +
++    // Turn off first nine LEDs
++    writel(FIRST_LEDS_MASK, GPIO_A_OUTPUT_SET);
 +
++    // Turn off tenth LED
++    writel(SECOND_LEDS_MASK, GPIO_B_OUTPUT_SET);
 +
++    // Enable first nine LEDs as outputs
++    writel(FIRST_LEDS_MASK, GPIO_A_OUTPUT_ENABLE_SET);
 +
++    // Enable tenth LED as output
++    writel(SECOND_LEDS_MASK, GPIO_B_OUTPUT_ENABLE_SET);
 +
++    // Turn on first nine LEDs sequentially
++    mdelay(1000);
++    writel(LED_D1, GPIO_A_OUTPUT_CLEAR);
++    mdelay(1000);
++    writel(LED_D2, GPIO_A_OUTPUT_CLEAR);
++    mdelay(1000);
++    writel(LED_D3, GPIO_A_OUTPUT_CLEAR);
++    mdelay(1000);
++    writel(LED_D4, GPIO_A_OUTPUT_CLEAR);
++    mdelay(1000);
++    writel(LED_D5, GPIO_A_OUTPUT_CLEAR);
++    mdelay(1000);
++    writel(LED_D6, GPIO_A_OUTPUT_CLEAR);
++    mdelay(1000);
++    writel(LED_D7, GPIO_A_OUTPUT_CLEAR);
++    mdelay(1000);
++    writel(LED_D8, GPIO_A_OUTPUT_CLEAR);
++    mdelay(1000);
++    writel(LED_D9, GPIO_A_OUTPUT_CLEAR);
 +
++    // Turn on tenth LED
++    mdelay(1000);
++    writel(LED_D10, GPIO_B_OUTPUT_CLEAR);
 +
++    // Disable primary, secondary and teriary GPIO functions for PWN line
++    writel(readl(SYS_CTRL_GPIO_PRIMSEL_CTRL_0) & ~PWM_MASK, SYS_CTRL_GPIO_PRIMSEL_CTRL_0);
++    writel(readl(SYS_CTRL_GPIO_SECSEL_CTRL_0)  & ~PWM_MASK, SYS_CTRL_GPIO_SECSEL_CTRL_0);
++    writel(readl(SYS_CTRL_GPIO_TERTSEL_CTRL_0) & ~PWM_MASK, SYS_CTRL_GPIO_TERTSEL_CTRL_0);
 +
++    // Turn off PWM line
++    writel(PWM_MASK, GPIO_A_OUTPUT_SET);
 +
++    // Enable PWM line as output
++    writel(PWM_MASK, GPIO_A_OUTPUT_ENABLE_SET);
 +
++    // Turn on PWM line
++    mdelay(1000);
++    writel(PWM_MASK, GPIO_A_OUTPUT_CLEAR);
++}
++#endif // CONFIG_HIPOX_LED_TEST
 +
++static void __init hipox_init_machine(void)
++{
++//printk("hipox_init_machine()\n");
++    /* Initialise the spinlock used to make GPIO register set access atomic */
++    spin_lock_init(&hipox_gpio_spinlock);
 +
++    /*
++     * Initialise the support for our multi-channel memory-to-memory DMAC
++     * The interrupt subsystem needs to be available before we can initialise
++     * the DMAC support
++     */
++    hipox_dma_init();
 +
++#ifdef CONFIG_DO_MEM_TEST
++    /*
++     * Do memory performance test
++     */
++    hipox_mem_test();
++#endif // CONFIG_DO_MEM_TEST
 +
++#ifdef CONFIG_LEON_START_EARLY
++    init_copro(leon_early_srec, 0);
++#endif // CONFIG_LEON_START_EARLY
 +
++#ifdef CONFIG_HIPOX_LED_TEST
++    test_leds_and_pwm();
++#endif // CONFIG_HIPOX_LED_TEST
 +
++      // Add any platform bus devices
++      platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
++}
 +
++void sata_power_off(void)
++{
++#ifdef CONFIG_HIPOX_SATA_POWER_1
++    // Disable power to SATA 1
++    printk(KERN_INFO "Turning off disk 1\n");
++    writel(SATA_POWER_1_MASK, SATA_POWER_1_OUTPUT_CLR_REG);
++#endif // CONFIG_HIPOX_SATA_POWER_1
 +
++#ifdef CONFIG_HIPOX_SATA_POWER_2
++    // Disable power to SATA 2
++    printk(KERN_INFO "Turning off disk 2\n");
++    writel(SATA_POWER_2_MASK, SATA_POWER_2_OUTPUT_CLR_REG);
++#endif // CONFIG_HIPOX_SATA_POWER_2
++}
 +
++MACHINE_START(HIPOX, "OXE810 based HydraIP")
++    /* Maintainer: Oxford Semiconductor Ltd */
++#ifdef CONFIG_ARCH_HIPOX_UART1
++    .phys_io = UART_1_BASE_PA,
++    .io_pg_offst = (((u32)UART_1_BASE) >> 18) & 0xfffc,
++#elif defined(CONFIG_ARCH_HIPOX_UART2)
++    .phys_io = UART_2_BASE_PA,
++    .io_pg_offst = (((u32)UART_2_BASE) >> 18) & 0xfffc,
++#elif defined(CONFIG_ARCH_HIPOX_UART3)
++    .phys_io = UART_3_BASE_PA,
++    .io_pg_offst = (((u32)UART_3_BASE) >> 18) & 0xfffc,
++#elif defined(CONFIG_ARCH_HIPOX_UART4)
++    .phys_io = UART_4_BASE_PA,
++    .io_pg_offst = (((u32)UART_4_BASE) >> 18) & 0xfffc,
++#endif
++    .boot_params = SDRAM_PA + 0x100,
++    .fixup = hipox_fixup,
++    .map_io = hipox_mapio,
++    .init_irq = hipox_init_irq,
++    .timer = &hipox_timer,
++    .init_machine = hipox_init_machine,
++MACHINE_END
 +
-diff -Nurd linux-2.6.24/arch/arm/mach-hipox/hipox-wd810-leds.c linux-2.6.24-oxe810/arch/arm/mach-hipox/hipox-wd810-leds.c
---- linux-2.6.24/arch/arm/mach-hipox/hipox-wd810-leds.c        1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mach-hipox/hipox-wd810-leds.c 2008-06-11 17:47:55.000000000 +0200
+diff -Nurd linux-2.6.24.4/arch/arm/mach-hipox/hipox-wd810-leds.c linux-2.6.24/arch/arm/mach-hipox/hipox-wd810-leds.c
+--- linux-2.6.24.4/arch/arm/mach-hipox/hipox-wd810-leds.c      1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/mach-hipox/hipox-wd810-leds.c        2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,1021 @@
 +/*
 + * linux/arch/arm/mach-hipox/hipox-wd810-leds.c
@@ -22307,20 +21531,374 @@ diff -Nurd linux-2.6.24/arch/arm/mach-hipox/hipox-wd810-leds.c linux-2.6.24-oxe8
 +}
 +
 +
-+module_init(hipox_wd810_leds_init);
-+module_exit(hipox_wd810_leds_exit);
-+MODULE_DESCRIPTION("hipox wd810 1NC/2NC LEDs");
-+MODULE_AUTHOR("Oxford Semiconductor Ltd");
-+MODULE_LICENSE("GPL");
-+/******************************* End of File *********************************/
-diff -Nurd linux-2.6.24/arch/arm/mach-hipox/hipox.c linux-2.6.24-oxe810/arch/arm/mach-hipox/hipox.c
---- linux-2.6.24/arch/arm/mach-hipox/hipox.c   1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mach-hipox/hipox.c    2008-06-11 17:47:55.000000000 +0200
-@@ -0,0 +1,1104 @@
++module_init(hipox_wd810_leds_init);
++module_exit(hipox_wd810_leds_exit);
++MODULE_DESCRIPTION("hipox wd810 1NC/2NC LEDs");
++MODULE_AUTHOR("Oxford Semiconductor Ltd");
++MODULE_LICENSE("GPL");
++/******************************* End of File *********************************/
+diff -Nurd linux-2.6.24.4/arch/arm/mach-hipox/i2s.c linux-2.6.24/arch/arm/mach-hipox/i2s.c
+--- linux-2.6.24.4/arch/arm/mach-hipox/i2s.c   1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/mach-hipox/i2s.c     2010-01-14 14:01:15.000000000 +0100
+@@ -0,0 +1,352 @@
++/* 
++ *  procfs3.c -  create a "file" in /proc, use the file_operation way
++ *            to manage the file.
++ */
++ 
++#include <linux/types.h>
++#include <linux/errno.h>
++#include <linux/init.h>
++#include <linux/kernel.h>     /* We're doing kernel work */
++#include <linux/module.h>     /* Specifically, a module */
++#include <linux/proc_fs.h>    /* Necessary because we use proc fs */
++#include <asm/uaccess.h>              /* for copy_*_user */
++#include "asm/arch-hipox/i2s.h"
++#include "asm/io.h"
++
++#define DRV_NAME              "i2s"
++#define DRV_VERSION   "0.1"
++#define PROC_ENTRY_FILENAME   "i2s"
++#define PROCFS_MAX_SIZE       2048
++
++
++
++MODULE_AUTHOR("Chris Ford");
++MODULE_DESCRIPTION("I2S Test module");
++MODULE_LICENSE("GPL");
++MODULE_VERSION(DRV_VERSION);
++
++/**
++ * The buffer (2k) for this module
++ *
++ */
++static char procfs_buffer[PROCFS_MAX_SIZE];
++
++/**
++ * The size of the data hold in the buffer
++ *
++ */
++static unsigned long procfs_buffer_size = 0;
++
++/**
++ * The structure keeping information about the /proc file
++ *
++ */
++static struct proc_dir_entry *Our_Proc_File;
++
++
++void RefreshI2SRegisters(void)
++{
++      int iLen = sprintf( procfs_buffer,  
++              "DumpI2SRegisters----------------------------------\n"
++              "                                                  \n"
++              "     TX_CONTROL                = 0x%08x\n"
++              "     TX_SETUP                  = 0x%08x\n"
++              "     TX_SETUP1                 = 0x%08x\n"
++              "     TX_STATUS                 = 0x%08x\n"
++              "     RX_CONTROL                = 0x%08x\n"
++              "     RX_SETUP                  = 0x%08x\n"
++              "     RX_SETUP1                 = 0x%08x\n"
++              "     RX_STATUS                 = 0x%08x\n"
++              "     TX_DEBUG                  = 0x%08x\n"
++              "     TX_DEBUG2                 = 0x%08x\n"
++              "     TX_DEBUG3                 = 0x%08x\n"
++              "     RX_DEBUG_                 = 0x%08x\n"
++              "     RX_DEBUG2                 = 0x%08x\n"
++              "     RX_DEBUG3                 = 0x%08x\n"
++              "     TX_BUFFER_LEVEL           = 0x%08x\n"
++              "     TX_BUFFER_INTERRUPT_LEVEL = 0x%08x\n"
++              "     RX_BUFFER_LEVEL           = 0x%08x\n"
++              "     RX_BUFFER_INTERRUPT_LEVEL = 0x%08x\n"
++              "     RX_SPDIF_DEBUG            = 0x%08x\n"
++              "     RX_SPDIF_DEBUG2           = 0x%08x\n",
++              (u32) __raw_readl( TX_CONTROL                 ),
++              (u32) __raw_readl( TX_SETUP                   ),
++              (u32) __raw_readl( TX_SETUP1                  ),
++              (u32) __raw_readl( TX_STATUS                  ),
++              (u32) __raw_readl( RX_CONTROL                 ),
++              (u32) __raw_readl( RX_SETUP                   ),
++              (u32) __raw_readl( RX_SETUP1                  ),
++              (u32) __raw_readl( RX_STATUS                  ),
++              (u32) __raw_readl( TX_DEBUG                   ),
++              (u32) __raw_readl( TX_DEBUG2                  ),
++              (u32) __raw_readl( TX_DEBUG3                  ),
++              (u32) __raw_readl( RX_DEBUG_                  ),
++              (u32) __raw_readl( RX_DEBUG2                  ),
++              (u32) __raw_readl( RX_DEBUG3                  ),
++              (u32) __raw_readl( TX_BUFFER_LEVEL            ),
++              (u32) __raw_readl( TX_BUFFER_INTERRUPT_LEVEL  ),
++              (u32) __raw_readl( RX_BUFFER_LEVEL            ),
++              (u32) __raw_readl( RX_BUFFER_INTERRUPT_LEVEL  ),
++              (u32) __raw_readl( RX_SPDIF_DEBUG             ),
++              (u32) __raw_readl( RX_SPDIF_DEBUG2            ) );
++      
++      procfs_buffer_size = iLen + sprintf( procfs_buffer + iLen, 
++              "     INTERRUPT_CONTROL_STATUS  = 0x%08x\n"
++              "     INTERRUPT_MASK            = 0x%08x\n"
++              "     VERSION                   = 0x%08x\n"
++              "     TX_DATA_IN_FORMAT         = 0x%08x\n"
++              "     TX_CHANNELS_ENABLE        = 0x%08x\n"
++              "     TX_WRITES_TO              = 0x%08x\n"
++              "     RX_DATA_OUT_FORMAT        = 0x%08x\n"
++              "     RX_CHANNELS_ENABLE        = 0x%08x\n"
++              "     RX_READS_FROM             = 0x%08x\n"
++              "     TX_CPU_DATA_WRITES_ALT    = 0x%08x\n"
++              "     RX_CPU_DATA_READS_ALT     = 0x%08x\n"
++              "     TX_CPU_DATA_WRITES        = 0x%08x\n"
++              "     RX_CPU_DATA_READS         = 0x%08x\n"
++              "\n"
++              "--------------------------------------------------\n",
++              (u32) __raw_readl( INTERRUPT_CONTROL_STATUS   ),
++              (u32) __raw_readl( INTERRUPT_MASK             ),
++              (u32) __raw_readl( VERSION                    ),
++              (u32) __raw_readl( TX_DATA_IN_FORMAT          ),
++              (u32) __raw_readl( TX_CHANNELS_ENABLE         ),
++              (u32) __raw_readl( TX_WRITES_TO               ),
++              (u32) __raw_readl( RX_DATA_OUT_FORMAT         ),
++              (u32) __raw_readl( RX_CHANNELS_ENABLE         ),
++              (u32) __raw_readl( RX_READS_FROM              ),
++              (u32) __raw_readl( TX_CPU_DATA_WRITES_ALT     ),
++              (u32) __raw_readl( RX_CPU_DATA_READS_ALT      ),
++              (u32) __raw_readl( TX_CPU_DATA_WRITES         ),
++              (u32) __raw_readl( RX_CPU_DATA_READS          ) );
++}
++
++
++void DumpI2SRegisters(void)
++{
++      RefreshI2SRegisters();
++      printk( KERN_INFO "%s", procfs_buffer );  
++      return;
++}
++
++
++/**
++ * This funtion is called when the /proc file is read
++ *
++ */
++static ssize_t procfs_read(
++      struct file *filp,      /* see include/linux/fs.h   */
++      char *buffer,           /* buffer to fill with data */
++      size_t length,          /* length of the buffer     */
++      loff_t * offset)
++{
++      static int finished = 0;
++
++      /* 
++       * We return 0 to indicate end of file, that we have
++       * no more information. Otherwise, processes will
++       * continue to read from us in an endless loop. 
++       */
++      if ( finished ) {
++              printk(KERN_INFO "procfs_read: END\n");
++              finished = 0;
++              return 0;
++      }
++      
++      finished = 1;
++              
++      /* 
++       * We use put_to_user to copy the string from the kernel's
++       * memory segment to the memory segment of the process
++       * that called us. get_from_user, BTW, is
++       * used for the reverse. 
++       */
++      if ( copy_to_user(buffer, procfs_buffer, procfs_buffer_size) ) {
++              return -EFAULT;
++      }
++
++      printk(KERN_INFO "procfs_read: read %lu bytes\n", procfs_buffer_size);
++
++      return procfs_buffer_size;      /* Return the number of bytes "read" */
++}
++
++/*
++ * This function is called when /proc is written
++ */
++static ssize_t
++procfs_write(struct file *file, const char *buffer, size_t len, loff_t * off)
++{
++      if ( len > PROCFS_MAX_SIZE )    {
++              procfs_buffer_size = PROCFS_MAX_SIZE;
++      }
++      else    {
++              procfs_buffer_size = len;
++      }
++      
++      if ( copy_from_user(procfs_buffer, buffer, procfs_buffer_size) ) {
++              return -EFAULT;
++      }
++
++      printk(KERN_INFO "procfs_write: write %s\n",buffer);
++      printk(KERN_INFO "procfs_write: write %lu bytes\n", procfs_buffer_size);
++      
++      return procfs_buffer_size;
++}
++
++/* 
++ * This function decides whether to allow an operation
++ * (return zero) or not allow it (return a non-zero
++ * which indicates why it is not allowed).
++ *
++ * The operation can be one of the following values:
++ * 0 - Execute (run the "file" - meaningless in our case)
++ * 2 - Write (input to the kernel module)
++ * 4 - Read (output from the kernel module)
++ *
++ * This is the real function that checks file
++ * permissions. The permissions returned by ls -l are
++ * for referece only, and can be overridden here.
++ */
++
++static int module_permission(struct inode *inode, int op, struct nameidata *foo)
++{
++      /* 
++       * We allow everybody to read from our module, but
++       * only root (uid 0) may write to it 
++       */
++       if (op == 4 || (op == 2 && current->euid == 0)) {
++               printk( KERN_INFO "Insufficient permissions\n");
++              return 0;
++       }
++
++      /* 
++       * If it's anything else, access is denied 
++       */
++      return -EACCES;
++}
++
++/* 
++ * The file is opened - we don't really care about
++ * that, but it does mean we need to increment the
++ * module's reference count. 
++ */
++int procfs_open(struct inode *inode, struct file *file)
++{
++      u32 temp = 0;
++      
++      /* Open an entry on the proc filesystem */
++      printk(KERN_INFO "I2S::procfs_open\n");
++      try_module_get(THIS_MODULE);
++      
++      // printk(KERN_INFO "I2S::pre-reg set..\n");
++      // RefreshI2SRegisters();
++
++      /* Setup the I2S TX Core... */
++      temp  = 1                 << TX_CONTROL_ENABLE        |
++              1                 << TX_CONTROL_FLUSH         |
++              0                 << TX_CONTROL_MUTE          |
++              0                 << TX_CONTROL_TRICK         |
++              0                 << TX_CONTROL_SPEED         |
++              1                 << TX_CONTROL_ABORT_DMA     |
++              0                 << TX_CONTROL_AHB_ENABLE    |
++              1                 << TX_CONTROL_QUAD_BURSTS;
++      __raw_writel( temp, TX_CONTROL );
++      
++      temp  = TRUE_I2S          << TX_SETUP_FORMAT          |
++              I2S_SLAVE         << TX_SETUP_MODE            |
++              0                 << TX_SETUP_FLOW_INVERT     |
++              0                 << TX_SETUP_POS_EDGE        |
++              0                 << TX_SETUP_CLOCK_STOP      |
++              0                 << TX_SETUP_SPLIT_QUAD      |
++              0                 << TX_SETUP_SPDIF_EN;
++      __raw_writel( temp, TX_SETUP );
++      
++      temp  = TWOS_COMPLIMENT   << TX_SETUP1_INPUT          |
++              0                 << TX_SETUP1_REVERSE        |
++              0                 << TX_SETUP1_INVERT         |
++              0                 << TX_SETUP1_BIG_ENDIAN     |
++              0                 << TX_SETUP1_QUAD_ENDIAN    |
++              0                 << TX_SETUP1_QUAD_SAMPLES   |
++              0                 << TX_SETUP1_FLOW_CONTROL;
++      __raw_writel( temp, TX_SETUP1 );
++      
++      /* Setup the I2S RX Core... */
++      
++      printk(KERN_INFO "\n\nI2S::post-reg set..\n");
++      RefreshI2SRegisters();
++      return 0;
++}
++
++/* 
++ * The file is closed - again, interesting only because
++ * of the reference count. 
++ */
++int procfs_close(struct inode *inode, struct file *file)
++{
++      printk(KERN_INFO "I2S::procfs_close\n");
++      module_put(THIS_MODULE);
++      return 0;               /* success */
++}
++
++static struct file_operations File_Ops_4_Our_Proc_File = {
++      .read    = procfs_read,
++      .write   = procfs_write,
++      .open    = procfs_open,
++      .release = procfs_close,
++};
++
++/* 
++ * Inode operations for our proc file. We need it so
++ * we'll have some place to specify the file operations
++ * structure we want to use, and the function we use for
++ * permissions. It's also possible to specify functions
++ * to be called for anything else which could be done to
++ * an inode (although we don't bother, we just put
++ * NULL). 
++ */
++
++static struct inode_operations Inode_Ops_4_Our_Proc_File = {
++      .permission = module_permission,        /* check for permissions */
++};
++
++/* 
++ * Module initialization and cleanup 
++ */
++static int __init hipox_i2s_init_module(void)
++{
++      printk(KERN_INFO "I2S::init_module\n");
++
++      /* create the /proc file */
++      Our_Proc_File = create_proc_entry(PROC_ENTRY_FILENAME, 0644, NULL);
++      
++      /* check if the /proc file was created successfuly */
++      if (Our_Proc_File == NULL){
++              printk(KERN_ALERT "Error: Could not initialize /proc/%s\n",
++                     PROC_ENTRY_FILENAME);
++              return -ENOMEM;
++      }
++      
++      Our_Proc_File->owner      = THIS_MODULE;
++      Our_Proc_File->proc_iops  = &Inode_Ops_4_Our_Proc_File;
++      Our_Proc_File->proc_fops  = &File_Ops_4_Our_Proc_File;
++      Our_Proc_File->mode       = S_IFREG | S_IRUGO | S_IWUSR;
++      Our_Proc_File->uid        = 0;
++      Our_Proc_File->gid        = 0;
++      Our_Proc_File->size       = 80;
++
++      printk(KERN_INFO "/proc/%s created\n", PROC_ENTRY_FILENAME);
++
++      return 0;       /* success */
++}
++
++static void __exit hipox_i2s_cleanup_module(void)
++{
++      printk(KERN_INFO "I2S::cleanup_module\n");
++      remove_proc_entry(PROC_ENTRY_FILENAME, &proc_root);
++      printk(KERN_INFO "/proc/%s removed\n", PROC_ENTRY_FILENAME);
++}
++
++module_init(hipox_i2s_init_module);
++module_exit(hipox_i2s_cleanup_module);
++
++
+diff -Nurd linux-2.6.24.4/arch/arm/mach-hipox/irq.c linux-2.6.24/arch/arm/mach-hipox/irq.c
+--- linux-2.6.24.4/arch/arm/mach-hipox/irq.c   1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/mach-hipox/irq.c     2010-01-14 14:01:15.000000000 +0100
+@@ -0,0 +1,59 @@
 +/*
-+ * linux/arch/arm/mach-hipox/hipox.c
-+ *
-+ * Copyright (C) 2005 Oxford Semiconductor Ltd
++ *  linux/arch/arm/mach-hipox/irq.c
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License as published by
@@ -22336,1094 +21914,1220 @@ diff -Nurd linux-2.6.24/arch/arm/mach-hipox/hipox.c linux-2.6.24-oxe810/arch/arm
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 + */
-+#include <linux/delay.h>
-+#include <linux/platform_device.h>
-+#include <linux/kernel.h>
 +#include <linux/init.h>
-+#include <linux/completion.h>
-+#include <linux/serial.h>
-+#include <linux/serial_core.h>
-+#include <linux/serial_8250.h>
++#include <linux/list.h>
++#include <asm/hardware.h>
++#include <asm/irq.h>
++#include <asm/mach/irq.h>
 +
-+#include <asm/sizes.h>
-+#include <asm/setup.h>
-+#include <asm/mach-types.h>
-+#include <asm/mach/arch.h>
-+#include <asm/mach/map.h>
-+#include <asm/arch/hardware.h>
-+#include <asm/arch/dma.h>
++static void HIPOX_mask_irq(unsigned int irq)
++{
++    *((volatile unsigned long*)(RPS_IRQ_DISABLE)) = (1UL << irq);
++}
 +
-+#ifdef CONFIG_DO_MEM_TEST
-+#include <linux/dma-mapping.h>
-+#include <asm/io.h>
-+#include <asm/arch/ahb_mon.h>
-+#endif // CONFIG_DO_MEM_TEST
++static void HIPOX_unmask_irq(unsigned int irq)
++{
++    *((volatile unsigned long*)RPS_IRQ_ENABLE) = (1UL << irq);
++}
 +
-+#include <asm/io.h>
++static struct irq_chip HIPOX_chip = {
++      .name   = "HIPOX",
++    .ack      = HIPOX_mask_irq,
++    .mask     = HIPOX_mask_irq,
++    .unmask = HIPOX_unmask_irq,
++};
 +
-+#ifdef CONFIG_LEON_START_EARLY
-+#include <asm/arch/leon.h>
-+#include <asm/arch/leon-early-prog.h>
-+#endif // CONFIG_LEON_START_EARLY
++void __init hipox_init_irq(void)
++{
++    unsigned irq;
 +
-+#ifdef CONFIG_HIPOX_PCI_RESET_GPIO
-+#if (CONFIG_HIPOX_PCI_RESET_GPIO < 32)
-+#define PCI_RESET_NUM               CONFIG_HIPOX_PCI_RESET_GPIO
-+#define PCI_RESET_PRISEL_REG        SYS_CTRL_GPIO_PRIMSEL_CTRL_0
-+#define PCI_RESET_SECSEL_REG        SYS_CTRL_GPIO_SECSEL_CTRL_0
-+#define PCI_RESET_TERSEL_REG        SYS_CTRL_GPIO_TERTSEL_CTRL_0
-+#define PCI_RESET_SET_OE_REG        GPIO_A_OUTPUT_ENABLE_SET
-+#define PCI_RESET_OUTPUT_SET_REG    GPIO_A_OUTPUT_SET
-+#define PCI_RESET_OUTPUT_CLR_REG    GPIO_A_OUTPUT_CLEAR
-+#else
-+#define PCI_RESET_NUM               ((CONFIG_HIPOX_PCI_RESET_GPIO) - 32)
-+#define PCI_RESET_PRISEL_REG        SYS_CTRL_GPIO_PRIMSEL_CTRL_1
-+#define PCI_RESET_SECSEL_REG        SYS_CTRL_GPIO_SECSEL_CTRL_1
-+#define PCI_RESET_TERSEL_REG        SYS_CTRL_GPIO_TERTSEL_CTRL_1
-+#define PCI_RESET_SET_OE_REG        GPIO_B_OUTPUT_ENABLE_SET
-+#define PCI_RESET_OUTPUT_SET_REG    GPIO_B_OUTPUT_SET
-+#define PCI_RESET_OUTPUT_CLR_REG    GPIO_B_OUTPUT_CLEAR
-+#endif
++    // Disable all IRQs
++    *((volatile unsigned long*)(RPS_IRQ_DISABLE)) = ~0UL;
 +
-+#define PCI_RESET_MASK (1UL << (PCI_RESET_NUM))
-+#endif // CONFIG_HIPOX_PCI_RESET_GPIO
++    // Disable FIQ
++    *((volatile unsigned long*)(RPS_FIQ_DISABLE)) = ~0UL;
 +
-+#define PCI_CLOCK_NUM               10
-+#define PCI_CLOCK_PRISEL_REG        SYS_CTRL_GPIO_PRIMSEL_CTRL_0
-+#define PCI_CLOCK_SET_OE_REG        GPIO_A_OUTPUT_ENABLE_SET
-+#define PCI_CLOCK_MASK              (1UL << (PCI_CLOCK_NUM))
++    // Initialise IRQ tracking structures
++    for (irq=0; irq < NR_IRQS; irq++)
++    {
++        set_irq_chip(irq, &HIPOX_chip);
++        set_irq_handler(irq, handle_level_irq);
++        set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
++    }
++}
 +
-+#ifdef CONFIG_HIPOX_SATA_POWER_GPIO_1
-+#if (CONFIG_HIPOX_SATA_POWER_GPIO_1 < 32)
-+#define SATA_POWER_1_NUM            CONFIG_HIPOX_SATA_POWER_GPIO_1
-+#define SATA_POWER_1_PRISEL_REG     SYS_CTRL_GPIO_PRIMSEL_CTRL_0
-+#define SATA_POWER_1_SECSEL_REG     SYS_CTRL_GPIO_SECSEL_CTRL_0
-+#define SATA_POWER_1_TERSEL_REG     SYS_CTRL_GPIO_TERTSEL_CTRL_0
-+#define SATA_POWER_1_SET_OE_REG     GPIO_A_OUTPUT_ENABLE_SET
-+#define SATA_POWER_1_OUTPUT_SET_REG GPIO_A_OUTPUT_SET
-+#define SATA_POWER_1_OUTPUT_CLR_REG GPIO_A_OUTPUT_CLEAR
-+#else
-+#define SATA_POWER_1_NUM            ((CONFIG_HIPOX_SATA_POWER_GPIO_1) - 32)
-+#define SATA_POWER_1_PRISEL_REG     SYS_CTRL_GPIO_PRIMSEL_CTRL_1
-+#define SATA_POWER_1_SECSEL_REG     SYS_CTRL_GPIO_SECSEL_CTRL_1
-+#define SATA_POWER_1_TERSEL_REG     SYS_CTRL_GPIO_TERTSEL_CTRL_1
-+#define SATA_POWER_1_SET_OE_REG     GPIO_B_OUTPUT_ENABLE_SET
-+#define SATA_POWER_1_OUTPUT_SET_REG GPIO_B_OUTPUT_SET
-+#define SATA_POWER_1_OUTPUT_CLR_REG GPIO_B_OUTPUT_CLEAR
-+#endif
+diff -Nurd linux-2.6.24.4/arch/arm/mach-hipox/Kconfig linux-2.6.24/arch/arm/mach-hipox/Kconfig
+--- linux-2.6.24.4/arch/arm/mach-hipox/Kconfig 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/mach-hipox/Kconfig   2010-01-14 14:01:15.000000000 +0100
+@@ -0,0 +1,574 @@
++if ARCH_HIPOX
 +
-+#define SATA_POWER_1_MASK   (1UL << (SATA_POWER_1_NUM))
-+#endif // CONFIG_HIPOX_SATA_POWER_GPIO_1
++menu "Oxford Semiconductor NAS Options"
 +
-+#ifdef CONFIG_HIPOX_SATA_POWER_GPIO_2
-+#if (CONFIG_HIPOX_SATA_POWER_GPIO_2 < 32)
-+#define SATA_POWER_2_NUM            CONFIG_HIPOX_SATA_POWER_GPIO_2
-+#define SATA_POWER_2_PRISEL_REG     SYS_CTRL_GPIO_PRIMSEL_CTRL_0
-+#define SATA_POWER_2_SECSEL_REG     SYS_CTRL_GPIO_SECSEL_CTRL_0
-+#define SATA_POWER_2_TERSEL_REG     SYS_CTRL_GPIO_TERTSEL_CTRL_0
-+#define SATA_POWER_2_SET_OE_REG     GPIO_A_OUTPUT_ENABLE_SET
-+#define SATA_POWER_2_OUTPUT_SET_REG GPIO_A_OUTPUT_SET
-+#define SATA_POWER_2_OUTPUT_CLR_REG GPIO_A_OUTPUT_CLEAR
-+#else
-+#define SATA_POWER_2_NUM            ((CONFIG_HIPOX_SATA_POWER_GPIO_2) - 32)
-+#define SATA_POWER_2_PRISEL_REG     SYS_CTRL_GPIO_PRIMSEL_CTRL_1
-+#define SATA_POWER_2_SECSEL_REG     SYS_CTRL_GPIO_SECSEL_CTRL_1
-+#define SATA_POWER_2_TERSEL_REG     SYS_CTRL_GPIO_TERTSEL_CTRL_1
-+#define SATA_POWER_2_SET_OE_REG     GPIO_B_OUTPUT_ENABLE_SET
-+#define SATA_POWER_2_OUTPUT_SET_REG GPIO_B_OUTPUT_SET
-+#define SATA_POWER_2_OUTPUT_CLR_REG GPIO_B_OUTPUT_CLEAR
-+#endif
++config ARCH_HIPOX_FPGA
++      bool "FPGA platform"
++      default n
++      help
++        This enables support for Oxsemi NAS SoC FPGA development platform
 +
-+#define SATA_POWER_2_MASK   (1UL << (SATA_POWER_2_NUM))
-+#endif // CONFIG_HIPOX_SATA_POWER_GPIO_2
++config HIPOX_CORE_CLK
++      int "Integrator core module processor clock frequency in MHz"
++      depends on ARCH_HIPOX_FPGA
++      default 175
++      help
++              Maximum reliable frequency 175MHz
 +
-+#ifdef CONFIG_HIPOX_USB_HUB_RESET_GPIO
-+#if (CONFIG_HIPOX_USB_HUB_RESET_GPIO < 32)
-+#define USB_HUB_RESET_NUM            CONFIG_HIPOX_USB_HUB_RESET_GPIO
-+#define USB_HUB_RESET_PRISEL_REG     SYS_CTRL_GPIO_PRIMSEL_CTRL_0
-+#define USB_HUB_RESET_SECSEL_REG     SYS_CTRL_GPIO_SECSEL_CTRL_0
-+#define USB_HUB_RESET_TERSEL_REG     SYS_CTRL_GPIO_TERTSEL_CTRL_0
-+#define USB_HUB_RESET_SET_OE_REG     GPIO_A_OUTPUT_ENABLE_SET
-+#define USB_HUB_RESET_OUTPUT_SET_REG GPIO_A_OUTPUT_SET
-+#define USB_HUB_RESET_OUTPUT_CLR_REG GPIO_A_OUTPUT_CLEAR
-+#else
-+#define USB_HUB_RESET_NUM            ((CONFIG_HIPOX_USB_HUB_RESET_GPIO) - 32)
-+#define USB_HUB_RESET_PRISEL_REG     SYS_CTRL_GPIO_PRIMSEL_CTRL_1
-+#define USB_HUB_RESET_SECSEL_REG     SYS_CTRL_GPIO_SECSEL_CTRL_1
-+#define USB_HUB_RESET_TERSEL_REG     SYS_CTRL_GPIO_TERTSEL_CTRL_1
-+#define USB_HUB_RESET_SET_OE_REG     GPIO_B_OUTPUT_ENABLE_SET
-+#define USB_HUB_RESET_OUTPUT_SET_REG GPIO_B_OUTPUT_SET
-+#define USB_HUB_RESET_OUTPUT_CLR_REG GPIO_B_OUTPUT_CLEAR
-+#endif
++config HIPOX_CORE_BUS_CLK_DIV
++      int "Integrator core module bus clock divider"
++      depends on ARCH_HIPOX_FPGA
++      default 4
++      help
++              Must be greater than 0
 +
-+#define USB_HUB_RESET_MASK    (1UL << (USB_HUB_RESET_NUM))
-+#endif // CONFIG_HIPOX_USB_HUB_RESET_GPIO
++config NOMINAL_PLL400_FREQ
++      int "The master clock frequency of the Soc"
++      default 400000000
++      help
++              The PLL400 clock is divided by 2 to drive the ARM clock and by
++              4 to drive the AHB clock
 +
-+extern void hipox_init_irq(void);
-+extern struct sys_timer hipox_timer;
++config NOMINAL_RPSCLK_FREQ
++      int "The input clock frequency to the RPS"
++      default 25000000
++      help
++              The RPS clock feeds into a prescaler and from there feeds the
++              RPS timers
 +
-+// The spinlock exported to allow atomic use of GPIO register set
-+spinlock_t hipox_gpio_spinlock;
++choice
++      prompt "HIPOX system type"
++      default HIPOX_VERSION_0X800
 +
-+// To hold LED inversion state
-+int hipox_global_invert_leds = 0;
-+#include <linux/module.h>
-+EXPORT_SYMBOL(hipox_global_invert_leds);
++config HIPOX_VERSION_0X800
++      bool "0X800"
++      select ARM_AMBA
++      help
++        Support for the 0X800 SoC
 +
-+static struct map_desc hipox_io_desc[] __initdata = {
-+    { CORE_MODULE_BASE,     __phys_to_pfn(CORE_MODULE_BASE_PA),     SZ_4K,   MT_DEVICE },
-+    { APB_BRIDGE_A_BASE,    __phys_to_pfn(APB_BRIDGE_A_BASE_PA),    SZ_16M,  MT_DEVICE },
-+    { STATIC_CONTROL_BASE,  __phys_to_pfn(STATIC_CONTROL_BASE_PA),  SZ_4K,   MT_DEVICE },
-+    { STATIC_CS0_BASE,      __phys_to_pfn(STATIC_CS0_BASE_PA),      SZ_4K,   MT_DEVICE },
-+    { STATIC_CS1_BASE,      __phys_to_pfn(STATIC_CS1_BASE_PA),      SZ_4K,   MT_DEVICE },
-+    { STATIC_CS2_BASE,      __phys_to_pfn(STATIC_CS2_BASE_PA),      SZ_4K,   MT_DEVICE },
-+    { APB_BRIDGE_B_BASE,    __phys_to_pfn(APB_BRIDGE_B_BASE_PA),    SZ_16M,  MT_DEVICE },
-+    { USB_BASE,             __phys_to_pfn(USB_BASE_PA),             SZ_4M,   MT_DEVICE },
-+    { MAC_BASE,             __phys_to_pfn(MAC_BASE_PA),             SZ_4M,   MT_DEVICE },
-+    { ROM_BASE,             __phys_to_pfn(ROM_BASE_PA),             SZ_16K,  MT_DEVICE },
-+    { PCI_CSRS_BASE,        __phys_to_pfn(PCI_CSRS_BASE_PA),        SZ_4K,   MT_DEVICE }
-+#ifdef CONFIG_SUPPORT_LEON
-+#if (CONFIG_LEON_PAGES == 1)
-+   ,{ LEON_IMAGE_BASE,                        __phys_to_pfn(LEON_IMAGE_BASE_PA),                      SZ_4K, MT_DEVICE }
-+#elif (CONFIG_LEON_PAGES == 2)
-+   ,{ LEON_IMAGE_BASE,                        __phys_to_pfn(LEON_IMAGE_BASE_PA),                      SZ_8K, MT_DEVICE }
-+#elif (CONFIG_LEON_PAGES == 3)
-+   ,{ LEON_IMAGE_BASE,                    __phys_to_pfn(LEON_IMAGE_BASE_PA),                  SZ_8K, MT_DEVICE }
-+   ,{ LEON_IMAGE_BASE+0x2000, __phys_to_pfn(LEON_IMAGE_BASE_PA+0x2000),       SZ_4K, MT_DEVICE }
-+#elif (CONFIG_LEON_PAGES == 4)
-+   ,{ LEON_IMAGE_BASE,                    __phys_to_pfn(LEON_IMAGE_BASE_PA),                  SZ_8K, MT_DEVICE }
-+   ,{ LEON_IMAGE_BASE+0x2000, __phys_to_pfn(LEON_IMAGE_BASE_PA+0x2000),       SZ_8K, MT_DEVICE }
-+#else
-+#error "Unsupported number of Leon code pages"
-+#endif // CONFIG_LEON_PAGES
-+#endif // CONFIG_SUPPORT_LEON
-+      /*
-+       * Upto 8 pages for GMAC/DMA descriptors plus ARM/Leon TSO workspace if
-+       * Leon TSO is in use
-+       */
-+   ,{ SRAM_BASE,            __phys_to_pfn(SRAM_PA),                 SZ_16K, MT_DEVICE }
-+   ,{ SRAM_BASE+0x4000,     __phys_to_pfn(SRAM_PA+0x4000),          SZ_16K, MT_DEVICE }
-+};
++config HIPOX_VERSION_0X810
++      bool "0X810"
++      select ARM_AMBA
++      help
++        Support for the 0X810 SoC
++
++config HIPOX_VERSION_0X850
++      bool "0X850"
++      help
++        Support for the 0X850 SoC
++endchoice
++
++config ARCH_HIPOX_UART1
++      bool "Support UART1"
++      default n
++      help
++              This enables UART1 to be accessible to Linux.
++              UARTs will be mapped to ttySn numbers from UART1 to UART4, only
++              including those UARTs selected to be present
++
++config ARCH_HIPOX_UART1_MODEM
++      bool "Support UART1 modem control lines"
++      depends on ARCH_HIPOX_UART1
++      default n
++      help
++              Multiplex the modem control lines from UART1 onto external pins
++
++config ARCH_HIPOX_UART2
++      bool "Support UART2"
++      default n
++      help
++              This enables UART2 to be accessible to Linux
++              UARTs will be mapped to ttySn numbers from UART1 to UART4, only
++              including those UARTs selected to be present
++
++config ARCH_HIPOX_UART2_MODEM
++      bool "Support UART2 modem control lines"
++      depends on ARCH_HIPOX_UART2
++      default n
++      help
++              Multiplex the modem control lines from UART2 onto external pins
++
++config ARCH_HIPOX_UART3
++      bool "Support UART3"
++      default n
++      help
++              This enables UAR3 to be accessible to Linux
++              UARTs will be mapped to ttySn numbers from UART1 to UART4, only
++              including those UARTs selected to be present
++
++config ARCH_HIPOX_UART3_MODEM
++      bool "Support UART3 modem control lines"
++      depends on ARCH_HIPOX_UART3
++      default n
++      help
++              Multiplex the modem control lines from UART3 onto external pins
++
++config ARCH_HIPOX_UART4
++      bool "Support UART4"
++      depends on !PCI
++      default n
++      help
++              This enables UART4 to be accessible to Linux
++              UARTs will be mapped to ttySn numbers from UART1 to UART4, only
++              including those UARTs selected to be present
++              UART4 always has its modem control lines available on external pins
++              when selected (overlaying PCI functions)
++
++config ARCH_HIPOX_PCI_REQGNT_0
++      bool "Enable req/gnt for PCI device 0"
++      depends on PCI
++      default n
++      help
++
++config ARCH_HIPOX_PCI_REQGNT_1
++      bool "Enable req/gnt for PCI device 1"
++      depends on PCI
++      default n
++      help
++
++config ARCH_HIPOX_PCI_REQGNT_2
++      bool "Enable req/gnt for PCI device 2"
++      depends on PCI
++      default n
++      help
++
++config ARCH_HIPOX_PCI_REQGNT_3
++      bool "Enable req/gnt for PCI device 3"
++      depends on PCI
++      default n
++      help
++
++config ARCH_HIPOX_PCI_CLKOUT_0
++      bool "Enable PCI clock output 0"
++      depends on PCI
++      default n
++      help
++
++config ARCH_HIPOX_PCI_CLKOUT_1
++      bool "Enable PCI clock output 1"
++      depends on PCI
++      default n
++      help
++
++config ARCH_HIPOX_PCI_CLKOUT_2
++      bool "Enable PCI clock output 2"
++      depends on PCI
++      default n
++      help
++
++config ARCH_HIPOX_PCI_CLKOUT_3
++      bool "Enable PCI clock output 3"
++      depends on PCI
++      default n
++      help
++
++config HIPOX_PCI_RESET
++      bool "Allow PCI reset to be toggled after power up"
++      depends on PCI
++      default n
++      help
++              The SoC requires that the PCI bus reset be toggled after the
++              rest of the SoC has emerged from reset
++
++config HIPOX_PCI_RESET_GPIO
++      int "GPIO line connected to PCI reset"
++      depends on HIPOX_PCI_RESET
++      default 12
++      help
++              The PCI bus requires a separate reset to be asserted after the
++              reset of the SoC has emerged from reset. This defines the GPIO
++              line which is connected to the PCI reset
++
++config HIPOX_SATA_POWER_1
++      bool "Allow control of SATA 1 disk power via GPIO"
++      default n
++      help
++              Allow SATA disk 1 power to be turned off via GPIO lines
++
++config HIPOX_SATA_POWER_GPIO_1
++      int "GPIO line connected to SATA power control for disk 1"
++      depends on HIPOX_SATA_POWER_1
++      default 15
++      help
++              The GPIO line that controls SATA disk 1 power
++
++config HIPOX_SATA_POWER_2
++      bool "Allow control of SATA disk 2 power via GPIO"
++      default n
++      help
++              Allow SATA disk 2 power to be turned off via GPIO lines
++
++config HIPOX_SATA_POWER_GPIO_2
++      int "GPIO line connected to SATA power control for disk 2"
++      depends on HIPOX_SATA_POWER_2
++      default 18
++      help
++              The GPIO line that controls SATA disk 2 power
++
++config FORCE_MAX_ZONEORDER
++      int "Max order of zoned buddy allocator"
++      default 11
++      help
++              The value to be assigned to MAX_ORDER
++
++config SRAM_NUM_PAGES
++      int "The number of SRAM memory pages present in the system"
++      default 8
++      help
++              Determines the number of pages of SRAM that are assumed to exist in the
++              system memory map
++
++config SUPPORT_LEON
++      bool "Include support for Leon"
++      default n
++
++config LEON_PAGES
++      int "The number of 4K pages of SRAM to reserve for the LEON program"
++      depends on SUPPORT_LEON
++      default 2
++      help
++              Determines the number of 4K pages of SRAM that are reserved for the
++              LEON program
++
++config LEON_COPRO
++      bool "Load LEON networking acceleration program"
++      depends on SUPPORT_LEON && HIPOX_VERSION_0X810
++      default n
++
++config LEON_OFFLOAD_TX
++      bool "Whether network Tx operations should be offloaded to the LEON"
++      depends on LEON_COPRO
++      default n
++
++config LEON_RESERVE_DMA_CHANNEL
++      bool "Whether to reserve the last DMA channel for the CoPro's use"
++      depends on LEON_OFFLOAD_TX
++      default n
++
++config LEON_OFFLOAD_TSO
++      bool "Whether network TSO operations should be offloaded to the LEON"
++      depends on LEON_OFFLOAD_TX
++      default n
++
++config LEON_START_EARLY
++      bool "Load LEON early startup program"
++      depends on SUPPORT_LEON
++      default n
++      help
++              For situations where the LEON is to run some code unrelated to
++              its normal network acceleration functions, this options causes
++              the LEON code to be loaded and the LEON started early in the
++              boot process
++
++config LEON_POWER_BUTTON_MONITOR
++      tristate "Load LEON power button monitoring program"
++      depends on SUPPORT_LEON
++      default n
++      help
++              Support powering down the system via a GPIO button and when the
++              system is powered down load a LEON program that will monitor the
++              button for attempts to power the system back on
++
++config HIPOX_POWER_BUTTON_GPIO
++      int "GPIO line connected to power button"
++      depends on LEON_POWER_BUTTON_MONITOR
++      default 33
++      help
++              Specifies the GPIO line to which the power button is connected
++
++config USER_RECOVERY_BUTTON_MONITOR
++      tristate "Load user recovery button monitoring program"
++      default n
++      help
++              Support User recovery of the system via a GPIO button. When the
++              system is power cycled after the use of this button, the admin
++              password and network settings are set to factory values.
++
++config HIPOX_USER_RECOVERY_BUTTON_GPIO
++      int "GPIO line connected to user recovery button"
++      depends on USER_RECOVERY_BUTTON_MONITOR
++      default 32
++      help
++              Specifies the GPIO line to which the user recovery button is 
++              connected.
++
++config HIPOX_DDR_MON
++      bool "Poll the DDR core bus monitors from timer tick interrupt"
++      default n
++
++config HIPOX_AHB_MON
++      bool "Include support for AHB monitors"
++      default n
++
++config HIPOX_MONITOR_SUBSAMPLE
++      int "Jiffy subsample factor for AHB monitor sampling"
++      depends on HIPOX_AHB_MON || HIPOX_DDR_MON
++      default 10
++      help
++              The factor by which to subsample the jiffy count to produce AHB monitor
++              sampling events
++
++config HIPOX_CACHE_LOCKDOWN
++      bool "Allow locking down part of the caches"
++      default n
++
++config HIPOX_CACHE_I_MASK
++      int "Bit mask for I cache lockdown"
++      depends on HIPOX_CACHE_LOCKDOWN
++      default 0
++      help
++              Allowable values are:
++              0 - No ways locked down
++              1 - One way locked down
++              3 - Two ways locked down
++              7 - Three ways locked down
 +
-+static struct resource usb_resources[] = {
-+      [0] = {
-+              .start          = USB_BASE_PA,
-+              .end            = USB_BASE_PA + 0x10000 - 1,
-+              .flags          = IORESOURCE_MEM,
-+      },
-+      [1] = {
-+              .start          = USB_FS_INTERRUPT,
-+              .end            = USB_FS_INTERRUPT,
-+              .flags          = IORESOURCE_IRQ,
-+      },
-+};
++config HIPOX_CACHE_D_MASK
++      int "Bit mask for D cache lockdown"
++      depends on HIPOX_CACHE_LOCKDOWN
++      default 0
++      help
++              Allowable values are:
++              0 - No ways locked down
++              1 - One way locked down
++              3 - Two ways locked down
++              7 - Three ways locked down
 +
-+static u64 usb_dmamask = ~(u32)0;
++config DO_MEM_TEST
++      bool "Perform memory copy throughput test during boot"
++      default 0
 +
-+static struct platform_device usb_device = {
-+      .name           = "hipox-ehci",
-+      .id             = 0,
-+      .dev = {
-+              .dma_mask               = &usb_dmamask,
-+              .coherent_dma_mask      = 0xffffffff,
-+      },
-+      .num_resources  = ARRAY_SIZE(usb_resources),
-+      .resource       = usb_resources,
-+};
++config CRYPTO_OXAESLRW
++      tristate "LRW-AES hardware support"
++      help
++        Driver for controlling the Ox-Semi OX800 cipher core for LRW-AES
++        encryption
 +
-+static struct platform_device *platform_devices[] __initdata = {
-+      &usb_device,
-+};
++config DESCRIPTORS_PAGES
++      int "The number of SRAM memory pages to reserve for DMA descriptors"
++      default 1
++      help
++              Determines the number of pages of SRAM that are reserved for DMA
++              descriptors
 +
-+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ)
++config ARCH_HIPOX_NUM_GMAC_DESCRIPTORS
++      int "The number of GMAC descriptors to allocate"
++      default 112
 +
-+#define INT_UART_BASE_BAUD (NOMINAL_SYSCLK)
++config ARCH_HIPOX_MAX_SATA_SG_ENTRIES
++      int "The max. number of SG DMA descriptors to use in the single transfer"
++      default 64
 +
-+#ifdef CONFIG_ARCH_HIPOX_UART1
-+static struct uart_port internal_serial_port_1 = {
-+      .membase        = (char *)(UART_1_BASE),
-+      .mapbase        = UART_1_BASE_PA,
-+      .irq            = UART_1_INTERRUPT,
-+      .flags          = STD_COM_FLAGS,
-+      .iotype         = UPIO_MEM,
-+      .regshift       = 0,
-+      .uartclk        = INT_UART_BASE_BAUD,
-+      .line           = 0,
-+      .type           = PORT_16550A,
-+      .fifosize       = 16
-+};
-+#endif // CONFIG_ARCH_HIPOX_UART1
++config TACHO_THERM_AND_FAN
++      tristate "Include support for the temperature sensing, and automatic fan control"
++      default n
 +
-+#ifdef CONFIG_ARCH_HIPOX_UART2
-+static struct uart_port internal_serial_port_2 = {
-+      .membase        = (char *)(UART_2_BASE),
-+      .mapbase        = UART_2_BASE_PA,
-+      .irq            = UART_2_INTERRUPT,
-+      .flags          = STD_COM_FLAGS,
-+      .iotype         = UPIO_MEM,
-+      .regshift       = 0,
-+      .uartclk        = INT_UART_BASE_BAUD,
-+      .line           = 0,
-+      .type           = PORT_16550A,
-+      .fifosize       = 16
-+};
-+#endif // CONFIG_ARCH_HIPOX_UART2
++config GPIO_TEST
++      tristate "Device driver for exercising GPIO block."
++      default n
++      help
++        Connect the I2C serial lines (SCLK, SCS, and SDT) together to run test
 +
-+#ifdef CONFIG_ARCH_HIPOX_UART3
-+static struct uart_port internal_serial_port_3 = {
-+      .membase        = (char *)(UART_3_BASE),
-+      .mapbase        = UART_3_BASE_PA,
-+      .irq            = UART_3_INTERRUPT,
-+      .flags          = STD_COM_FLAGS,
-+      .iotype         = UPIO_MEM,
-+      .regshift       = 0,
-+      .uartclk        = INT_UART_BASE_BAUD,
-+      .line           = 0,
-+      .type           = PORT_16550A,
-+      .fifosize       = 16
-+};
-+#endif // CONFIG_ARCH_HIPOX_UART3
++config HIPOX_RTC
++      tristate "Probe for m41t00 RTC"
++      select I2C
++      select I2C_ALGOBIT
++      select I2C_HIPOX_BITBASH
++      select RTC_CLASS
++      select RTC_DRV_DS1307
++      default n
++      help
++        The M41T00 RTC provides basic time save and restore.
++        The device is probed for on the HIPOX bit-bash I2C bus.
 +
-+#ifdef CONFIG_ARCH_HIPOX_UART4
-+static struct uart_port internal_serial_port_4 = {
-+      .membase        = (char *)(UART_4_BASE),
-+      .mapbase        = UART_4_BASE_PA,
-+      .irq            = UART_4_INTERRUPT,
-+      .flags          = STD_COM_FLAGS,
-+      .iotype         = UPIO_MEM,
-+      .regshift       = 0,
-+      .uartclk        = INT_UART_BASE_BAUD,
-+      .line           = 0,
-+      .type           = PORT_16550A,
-+      .fifosize       = 16
-+};
-+#endif // CONFIG_ARCH_HIPOX_UART4
++config I2S
++      tristate "I2S test interface"
++      default n
++      help
++        Say Y here to use i2s
++        This support is also available as a module. If so, the module will be
++        called i2s.
 +
-+static void __init hipox_mapio(void)
-+{
-+    unsigned int uart_line=0;
++config PCI_HIPOX_CARDBUS
++    bool "Switches from a PCI/Mini-PCI bus to a Cardbus bus."
++    depends on PCI && ARCH_HIPOX_FPGA
++    ---help---
++      This option limits scanning of the bus to omit the Via SATA interface.
++      This makes the bus compatible with cardbus cards that expect to be the 
++      only PCI device on the bus.
 +
-+//printk("hipox_mapio()\n");
++config DPE_TEST
++      tristate "Test the DPE core"
++      default n
 +
-+    // Setup kernel mappings for hardware cores
-+    iotable_init(hipox_io_desc, ARRAY_SIZE(hipox_io_desc));
++config HIPOX_EARLY_PRINTK
++      bool "Whether to output to printascii from printk"
++      depends on DEBUG_LL
++      help
++              If both CONFIG_DEBUG_LL and this option are selected, then each printk
++              call will duplicate the message in a call to printascii to get very
++              early console output
 +
-+#ifdef CONFIG_ARCH_HIPOX_FPGA    
-+    // Setup the ARM926-EJ-S integrator module clock and bus clock divider
-+    asm volatile(
-+        "mov r3,%2,LSL #4;"     /* Bus clock divider = ((n+1) << 4) */
-+        "sub r3,r3,#16;"
-+        "mov r0,%1;"            /* Processor clock frequency */
-+        "sub r0,r0,#8;"         /* correction for MHz */
-+        "and r0,r0,#0xFF;"      /* ensure byte value */
-+        "mov r2,%0;"            /* read CM base value */
-+        "ldr r1,[r2,#8];"       /* read CM_OSC */
-+        "bic r1,r1,#0x0FF;"     /* clear bottom byte r1 */
-+        "orr r1,r1,r0;"         /* write in new clock values */
-+        "ldr r4,[r2,#0x24];"    /* read CM_INIT */
-+        "bic r4,r4,#0x070;"     /* clear bits [6:4] */
-+        "orr r4,r4,r3;"         /* write in new clock values */
-+        "mov r0,#0xA000;"
-+        "orr r0,r0,#0x5F;"      /* build 0xA05F in r0 */
-+        "str r0,[r2,#0x14];"    /* write to unlock CM_LOCK */
-+        "str r1,[r2,#8];"       /* write value back */
-+        "str r4,[r2,#0x24];"    /* write HCLK value back */
-+        "str r1,[r2,#0x14];"    /* write in any value to relock CM_LOCK */
-+        :
-+        : "r" (CORE_MODULE_BASE), "r" (CONFIG_HIPOX_CORE_CLK), "r" (CONFIG_HIPOX_CORE_BUS_CLK_DIV)
-+        : "r0","r1","r2","r3","r4");
-+#endif // CONFIG_ARCH_HIPOX_FPGA
++config HIPOX_INSTRUMENT_COPIES
++      bool "Instrument copy_to_user and copy_from_user"
++      default n
 +
-+#ifdef CONFIG_HIPOX_VERSION_0X800
-+    // Configure the DDR controller arbitration scheme
-+    *(volatile u32*)DDR_ARB_REG = ((1UL << DDR_ARB_DATDIR_NCH_BIT) |
-+                                   (1UL << DDR_ARB_DATDIR_EN_BIT)  |
-+                                   (1UL << DDR_ARB_REQAGE_EN_BIT)  |
-+                                   (1UL << DDR_ARB_LRUBANK_EN_BIT) |
-+                                   (1UL << DDR_ARB_MIDBUF_BIT));
++config HIPOX_INSTRUMENT_COPIES_THRESHOLD
++      int "The threshold above which copies will be instrumented"
++      depends on HIPOX_INSTRUMENT_COPIES
++      default 0
 +
-+    // Setup the DDR client read buffers
-+    // NB 0X800 ASIC bug means DMA read buffers should never be enabled
-+    *(volatile u32*)DDR_AHB_REG = ((1UL << DDR_AHB_NO_RCACHE_ARMD_BIT)  |
-+                                   /*(1UL << DDR_AHB_NO_RCACHE_ARMI_BIT)  |*/
-+                                   (1UL << DDR_AHB_NO_RCACHE_COPRO_BIT) |
-+                                   (1UL << DDR_AHB_NO_RCACHE_DMAA_BIT)  |
-+                                   (1UL << DDR_AHB_NO_RCACHE_DMAB_BIT)  |
-+                                   /* (1UL << DDR_AHB_NO_RCACHE_PCI_BIT)   |
-+                                   (1UL << DDR_AHB_NO_RCACHE_GMAC_BIT)  |*/
-+                                   (1UL << DDR_AHB_NO_RCACHE_USB_BIT));
++config HIPOX_INSTRUMENT_COPIES_TIME
++      bool "Whether to print copy timing to console"
++      depends on HIPOX_INSTRUMENT_COPIES
++      default n
 +
-+    // Ignore HPROT for all clients except ARM data, as ARM Linux interrupt
-+      // latency will mask any slight delay in data written by cores getting to
-+      // memory after the core raises an interrupt
-+      *(volatile u32*)DDR_AHB2_REG = ((1UL << DDR_AHB2_IGNORE_HPROT_ARMI_BIT)  |
-+                                                                       (1UL << DDR_AHB2_IGNORE_HPROT_COPRO_BIT) |
-+                                                                       (1UL << DDR_AHB2_IGNORE_HPROT_DMAA_BIT)  |
-+                                                                       (1UL << DDR_AHB2_IGNORE_HPROT_DMAB_BIT)  |
-+                                                                       (1UL << DDR_AHB2_IGNORE_HPROT_PCI_BIT)   |
-+                                                                       (1UL << DDR_AHB2_IGNORE_HPROT_GMAC_BIT)  |
-+                                                                       (1UL << DDR_AHB2_IGNORE_HPROT_USB_BIT));
-+#elif CONFIG_HIPOX_VERSION_0X810
-+    // Configure the DDR controller arbitration scheme
-+    *(volatile u32*)DDR_ARB_REG = ((1UL << DDR_ARB_DATDIR_NCH_BIT) |
-+                                   (1UL << DDR_ARB_DATDIR_EN_BIT)  |
-+                                   (1UL << DDR_ARB_REQAGE_EN_BIT)  |
-+                                   (1UL << DDR_ARB_LRUBANK_EN_BIT) |
-+                                   (1UL << DDR_ARB_MIDBUF_BIT));
++config HIPOX_INSTRUMENT_COPIES_GPIO
++      bool "Whether to toggle a GPIO around copies"
++      depends on HIPOX_INSTRUMENT_COPIES
++      default n
 +
-+      // Configure read buffers - Do not disable any read buffers
-+      *(volatile u32*)DDR_AHB_REG = 0UL;
++config HIPOX_DMA_COPIES
++      bool "Whether to use DMA for larger user-kernel copies"
++      default n
++      
++config HIPOX_DMA_COPY_THRESHOLD
++      int "The threshold above which DMA will be used for copies"
++      depends on HIPOX_DMA_COPIES
++      default 1024
 +
-+      // Configure wrapping - Ignore wrap
-+      // Configure HPROT - Ignore all HPROT except ARM data
-+      *(volatile u32*)DDR_AHB2_REG = ((1UL << DDR_AHB2_IGNORE_WRAP_ARMD_BIT)   |
-+                                    (1UL << DDR_AHB2_IGNORE_WRAP_ARMI_BIT)   |
-+                                    (1UL << DDR_AHB2_IGNORE_WRAP_COPRO_BIT)  |
-+                                    (1UL << DDR_AHB2_IGNORE_WRAP_DMAA_BIT)   |
-+                                    (1UL << DDR_AHB2_IGNORE_WRAP_DMAB_BIT)   |
-+                                    (1UL << DDR_AHB2_IGNORE_WRAP_PCI_BIT)    |
-+                                    (1UL << DDR_AHB2_IGNORE_WRAP_GMAC_BIT)   |
-+                                    (1UL << DDR_AHB2_IGNORE_WRAP_US_BIT)     |
-+                                    (1UL << DDR_AHB2_IGNORE_HPROT_ARMI_BIT)  |
-+                                    (1UL << DDR_AHB2_IGNORE_HPROT_COPRO_BIT) |
-+                                    (1UL << DDR_AHB2_IGNORE_HPROT_DMAA_BIT)  |
-+                                    (1UL << DDR_AHB2_IGNORE_HPROT_DMAB_BIT)  |
-+                                    (1UL << DDR_AHB2_IGNORE_HPROT_PCI_BIT)   |
-+                                    (1UL << DDR_AHB2_IGNORE_HPROT_GMAC_BIT)  |
-+                                    (1UL << DDR_AHB2_IGNORE_HPROT_USB_BIT));
++config HIPOX_AHB_MONITOR_MODULE
++      tristate "Creates a loadable module to control the AHB monitors"
++      default n
++      help
++              This module publishes the current values of the AHB
++              monitors in the /proc filing system.
++              The monitors can be controlled by writing into this
++              filing system
 +
-+      // Configure burst ordering - Do not disable burst ordering
-+      // Configure non-cachable - Do not prevent non-cachable accesses from using read buffers
-+      *(volatile u32*)DDR_AHB3_REG = 0UL;
++config HIPOX_USB_TEST_MODES
++      tristate "Create a loadable module to control the USB port test modes"
++      default n
++      help
++              This module reports the port status and allows setting
++              of the test mode in the port register via the /proc 
++              filing system.
 +
-+      // Configure read buffer timeout - Do not enable read buffer invalidate after timeout
-+      // Configure write behind - Enable write behind coherency
-+      *(volatile u32*)DDR_AHB4_REG = ((1UL << DDR_AHB4_EN_WRBEHIND_ARMD_BIT)  |
-+                                                                       (1UL << DDR_AHB4_EN_WRBEHIND_ARMI_BIT)  |
-+                                                                       (1UL << DDR_AHB4_EN_WRBEHIND_COPRO_BIT) |
-+                                                                       (1UL << DDR_AHB4_EN_WRBEHIND_DMAA_BIT)  |
-+                                                                       (1UL << DDR_AHB4_EN_WRBEHIND_DMAB_BIT)  |
-+                                                                       (1UL << DDR_AHB4_EN_WRBEHIND_PCI_BIT)   |
-+                                                                       (1UL << DDR_AHB4_EN_WRBEHIND_GMAC_BIT)  |
-+                                                                       (1UL << DDR_AHB4_EN_WRBEHIND_USB_BIT));
++config HIPOX_FRONT_LAMP_CONTROL
++      tristate "Front Panel LED control system"
++      depends on LEDS_CLASS
++      default n
++      help
++              This module reports drives a number of GPIOs as PWM signals to drive
++              front panel LEDs. The pattern displayed is dependent on system state.
 +
-+#endif // CONFIG_HIPOX_VERSION_0X8xx
++config LEDS_TRIGGER_SATA_DISK
++      tristate "Front Panel SATA disk activity lamp control system"
++      default n
++      help
++              This module reports drives the SATA disk activity lamp.
 +
-+    // Enable all DDR client interfaces
-+    *(volatile u32*)DDR_BLKEN_REG |= (((1UL << DDR_BLKEN_CLIENTS_NUM_BITS) - 1) << DDR_BLKEN_CLIENTS_BIT);
++config HIPOX_LED_TEST
++      bool "Exercise the WD LEDs"
++      default n
 +
-+#ifdef CONFIG_ARCH_HIPOX_UART1
-+    // Block reset UART1
-+    *(volatile u32*)SYS_CTRL_RSTEN_SET_CTRL = (1UL << SYS_CTRL_RSTEN_UART1_BIT);
-+    *(volatile u32*)SYS_CTRL_RSTEN_CLR_CTRL = (1UL << SYS_CTRL_RSTEN_UART1_BIT);
++config HIPOX_I2C_SDA
++      int "I2C bit-bash data line"
++      default 2
 +
-+    // Route UART1 SOUT onto external pin
-+    *(volatile u32*)SYS_CTRL_GPIO_PRIMSEL_CTRL_0 &= ~0x80000000;
-+    *(volatile u32*)SYS_CTRL_GPIO_SECSEL_CTRL_0  &= ~0x80000000;
-+    *(volatile u32*)SYS_CTRL_GPIO_TERTSEL_CTRL_0 |=  0x80000000;
++config HIPOX_I2C_SCL
++      int "I2C bit-bash clock line"
++      default 3
 +
-+    // Route UART1 SIN onto external pin
-+    *(volatile u32*)SYS_CTRL_GPIO_PRIMSEL_CTRL_1 &= ~0x00000001;
-+    *(volatile u32*)SYS_CTRL_GPIO_SECSEL_CTRL_1  &= ~0x00000001;
-+    *(volatile u32*)SYS_CTRL_GPIO_TERTSEL_CTRL_1 |=  0x00000001;
++config        HIPOX_USB_PORTA_POWER_CONTROL
++      bool "Support USB port A power control lines"
++      default n
++      help
++              Whether to support power switch out and monitor in via GPIOs
++              for USB port A
 +
-+    // Setup GPIO line direction for UART1 SOUT
-+    *(volatile u32*)GPIO_A_OUTPUT_ENABLE_SET   |= 0x80000000;
++config        HIPOX_USB_PORTB_POWER_CONTROL
++      bool "Support USB port B power control lines"
++      default n
++      help
++              Whether to support power switch out and monitor in via GPIOs
++              for USB port B
 +
-+    // Setup GPIO line direction for UART1 SIN
-+    *(volatile u32*)GPIO_B_OUTPUT_ENABLE_CLEAR |= 0x00000001;
++config        HIPOX_USB_PORTC_POWER_CONTROL
++      bool "Support USB port C power control lines"
++      default n
++      help
++              Whether to support power switch out and monitor in via GPIOs
++              for USB port C
 +
-+#ifdef CONFIG_ARCH_HIPOX_UART1_MODEM
-+    // Route UART1 modem control lines onto external pins
-+    *(volatile u32*)SYS_CTRL_GPIO_PRIMSEL_CTRL_0 &= ~0x78000000;
-+    *(volatile u32*)SYS_CTRL_GPIO_SECSEL_CTRL_0  &= ~0x78000000;
-+    *(volatile u32*)SYS_CTRL_GPIO_TERTSEL_CTRL_0 |=  0x78000000;
++config HIPOX_USB_OVERCURRENT_POLARITY_NEGATIVE
++      bool "Set USB power monitor input polarity to negative"
++      default n
++      help
++              n - Positive polarity
++              y - Negative polarity
 +
-+    *(volatile u32*)SYS_CTRL_GPIO_PRIMSEL_CTRL_1 &= ~0x00000006;
-+    *(volatile u32*)SYS_CTRL_GPIO_SECSEL_CTRL_1  &= ~0x00000006;
-+    *(volatile u32*)SYS_CTRL_GPIO_TERTSEL_CTRL_1 |=  0x00000006;
++config HIPOX_USB_POWER_SWITCH_POLARITY_NEGATIVE
++      bool "Set USB power switch output polarity to negative"
++      default n
++      help
++              n - Positive polarity
++              y - Negative polarity
 +
-+    // Setup GPIO line directions for UART1 modem control lines
-+    *(volatile u32*)GPIO_A_OUTPUT_ENABLE_SET   |= 0x08000000;
-+    *(volatile u32*)GPIO_A_OUTPUT_ENABLE_CLEAR |= 0x70000000;
++config WDC_FAN_HIPOX800
++      tristate "WD NetCenter/2NC Fan control driver"
++      default n
++      help
++              This driver allows user-mode applications to control the cooling
++              fan on Western Digital's NetCenter/2NC platform.
 +
-+    *(volatile u32*)GPIO_B_OUTPUT_ENABLE_SET   |= 0x00000004;
-+    *(volatile u32*)GPIO_B_OUTPUT_ENABLE_CLEAR |= 0x00000002;
-+#endif // CONFIG_ARCH_HIPOX_UART1_MODEM
++config HIPOX_MAP_SRAM
++      bool "Allow part of kernel to be mapped into SRAM"
++      default n
 +
-+    // Give Linux a contiguous numbering scheme for available UARTs
-+    internal_serial_port_1.line = uart_line++;
-+    early_serial_setup(&internal_serial_port_1);
-+#endif // CONFIG_ARCH_HIPOX_UART1
++config HIPOX_COPY_CODE_TO_SRAM
++      bool "Copy part of kernel to SRAM"
++      depends on HIPOX_MAP_SRAM
++      default n
 +
-+#ifdef CONFIG_ARCH_HIPOX_UART2
-+    // Block reset UART2
-+    *(volatile u32*)SYS_CTRL_RSTEN_SET_CTRL = (1UL << SYS_CTRL_RSTEN_UART2_BIT);
-+    *(volatile u32*)SYS_CTRL_RSTEN_CLR_CTRL = (1UL << SYS_CTRL_RSTEN_UART2_BIT);
++config HIPOX_SUID_INHERIT
++      bool "Make SUID be inherited by subdirectories"
++      default n
 +
-+    // Route UART2 SIN/SOUT onto external pin
-+    *(volatile u32*)SYS_CTRL_GPIO_PRIMSEL_CTRL_0 &= ~0x00500000;
-+    *(volatile u32*)SYS_CTRL_GPIO_SECSEL_CTRL_0  &= ~0x00500000;
-+    *(volatile u32*)SYS_CTRL_GPIO_TERTSEL_CTRL_0 |=  0x00500000;
++config HIPOX_USB_HUB_SUPPORT
++      bool "Enable support for on-board USB hub"
++      default n
 +
-+    // Setup GPIO line directions for UART2 SIN/SOUT
-+    *(volatile u32*)GPIO_A_OUTPUT_ENABLE_SET   |= 0x00100000;
-+    *(volatile u32*)GPIO_A_OUTPUT_ENABLE_CLEAR |= 0x00400000;
++config HIPOX_USB_CKOUT
++      bool "Enable output of 12MHz USB clock on GPIO 10"
++      depends on HIPOX_USB_HUB_SUPPORT
++      default n
 +
-+#ifdef CONFIG_ARCH_HIPOX_UART2_MODEM
-+    // Route UART2 modem control lines onto external pins
-+    *(volatile u32*)SYS_CTRL_GPIO_PRIMSEL_CTRL_0 &= ~0x07800300;
-+    *(volatile u32*)SYS_CTRL_GPIO_SECSEL_CTRL_0  &= ~0x07800300;
-+    *(volatile u32*)SYS_CTRL_GPIO_TERTSEL_CTRL_0 |=  0x07800300;
++config HIPOX_USB_HUB_RESET_CONTROL
++      bool "Control the USB hub reset line"
++      depends on HIPOX_USB_HUB_SUPPORT
++      default n
 +
-+    // Setup GPIO line directions for UART2 modem control lines
-+    *(volatile u32*)GPIO_A_OUTPUT_ENABLE_SET   |= 0x02000200;
-+    *(volatile u32*)GPIO_A_OUTPUT_ENABLE_CLEAR |= 0x05800100;
-+#endif // CONFIG_ARCH_HIPOX_UART2_MODEM
++config HIPOX_USB_HUB_RESET_GPIO
++      int "The GPIO connected to the USB hub reset"
++      depends on HIPOX_USB_HUB_RESET_CONTROL
++      default 27
 +
-+    // Give Linux a contiguous numbering scheme for available UARTs
-+    internal_serial_port_2.line = uart_line++;
-+    early_serial_setup(&internal_serial_port_2);
-+#endif // CONFIG_ARCH_HIPOX_UART2
++config HIPOX_USB_HUB_RESET_ACTIVE_HIGH
++      int "Set to 1 for active high, 0 for active low reset"
++      depends on HIPOX_USB_HUB_RESET_CONTROL
++      default 1
 +
-+#ifdef CONFIG_ARCH_HIPOX_UART3
-+    // Block reset UART3
-+    *(volatile u32*)SYS_CTRL_RSTEN_SET_CTRL = (1UL << SYS_CTRL_RSTEN_UART3_BIT);
-+    *(volatile u32*)SYS_CTRL_RSTEN_CLR_CTRL = (1UL << SYS_CTRL_RSTEN_UART3_BIT);
++config HIPOX_USB_HUB_RESET_TOGGLE
++      bool "Select to toggle reset, do not select to just deassert reset"
++      depends on HIPOX_USB_HUB_RESET_CONTROL
++      default y
 +
-+    // Route UART3 SIN/SOUT onto external pin
-+    *(volatile u32*)SYS_CTRL_GPIO_PRIMSEL_CTRL_0 &= ~0x000000C0;
-+    *(volatile u32*)SYS_CTRL_GPIO_SECSEL_CTRL_0  &= ~0x000000C0;
-+    *(volatile u32*)SYS_CTRL_GPIO_TERTSEL_CTRL_0 |=  0x000000C0;
++config HIPOX_USB_HUB_RESET_PERIOD_MS
++      int "The period for which the USB hub reset should be asserted in milliseconds"
++      depends on HIPOX_USB_HUB_RESET_TOGGLE
++      default 100
 +
-+    // Setup GPIO line directions for UART3 SIN/SOUT
-+    *(volatile u32*)GPIO_A_OUTPUT_ENABLE_SET   |= 0x00000080;
-+    *(volatile u32*)GPIO_A_OUTPUT_ENABLE_CLEAR |= 0x00000040;
++endmenu
 +
-+    // Enable UART3 interrupt
-+    *(volatile u32*)SYS_CTRL_UART_CTRL |= (1UL << SYS_CTRL_UART3_IQ_EN);
++endif
+diff -Nurd linux-2.6.24.4/arch/arm/mach-hipox/leds.c linux-2.6.24/arch/arm/mach-hipox/leds.c
+--- linux-2.6.24.4/arch/arm/mach-hipox/leds.c  1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/mach-hipox/leds.c    2010-01-14 14:01:15.000000000 +0100
+@@ -0,0 +1,212 @@
++/*
++ * linux/arch/arm/mach-hipox/leds.c
++ *
++ * Copyright (C) 2005 Oxford Semiconductor Ltd
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++#define DEBUG
 +
-+#ifdef CONFIG_ARCH_HIPOX_UART3_MODEM
-+    // Route UART3 modem control lines onto external pins
-+    *(volatile u32*)SYS_CTRL_GPIO_PRIMSEL_CTRL_0 &= ~0x0000003f;
-+    *(volatile u32*)SYS_CTRL_GPIO_SECSEL_CTRL_0  &= ~0x0000003f;
-+    *(volatile u32*)SYS_CTRL_GPIO_TERTSEL_CTRL_0 |=  0x0000003f;
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/timer.h>
++#include <linux/interrupt.h>
 +
-+    // Setup GPIO line directions for UART3 modem control lines
-+    *(volatile u32*)GPIO_A_OUTPUT_ENABLE_SET   |= 0x00000030;
-+    *(volatile u32*)GPIO_A_OUTPUT_ENABLE_CLEAR |= 0x0000000f;
-+#endif // CONFIG_ARCH_HIPOX_UART3_MODEM
++#include <linux/platform_device.h>
 +
-+    // Give Linux a contiguous numbering scheme for available UARTs
-+    internal_serial_port_3.line = uart_line++;
-+    early_serial_setup(&internal_serial_port_3);
-+#endif // CONFIG_ARCH_HIPOX_UART3
 +
-+#ifdef CONFIG_ARCH_HIPOX_UART4
-+    // Block reset UART4
-+    *(volatile u32*)SYS_CTRL_RSTEN_SET_CTRL = (1UL << SYS_CTRL_RSTEN_UART4_BIT);
-+    *(volatile u32*)SYS_CTRL_RSTEN_CLR_CTRL = (1UL << SYS_CTRL_RSTEN_UART4_BIT);
++#include <linux/leds.h>
++ 
++#include <asm/hardware.h>
++
++#define DEBUG_PRINT(A) printk(KERN_NOTICE A)
++
++#define writel(data,address) (*(volatile u32 *) address = data)
++#define readl(address)       (*(volatile u32 *) address)
 +
-+    // Enable UART4 interrupt
-+    *(volatile u32*)SYS_CTRL_UART_CTRL |= (1UL << SYS_CTRL_UART4_IQ_EN);
++/* run pwm refresh at approximately 100Hz to avoid flicker */
++/* resolution is 8bits, sys clock 200MHz divider is therefore 7812 less 1 cycle */
++#define PWM_PERIOD  (7811)
 +
-+    // Enable UART4 to override PCI functions onto GPIOs
-+    *(volatile u32*)SYS_CTRL_UART_CTRL |= (1UL << SYS_CTRL_UART4_NOT_PCI_MODE);
++#define MAX_PWMS     16
 +
-+    internal_serial_port_4.line = uart_line++;
-+    early_serial_setup(&internal_serial_port_4);
-+#endif // CONFIG_ARCH_HIPOX_UART4
++static void ramp_power_on_leds(unsigned long data);
 +
-+#ifdef CONFIG_PCI
-+    // Block reset PCI core
-+    *(volatile u32*)SYS_CTRL_RSTEN_SET_CTRL = (1UL << SYS_CTRL_RSTEN_PCI_BIT);
-+    *(volatile u32*)SYS_CTRL_RSTEN_CLR_CTRL = (1UL << SYS_CTRL_RSTEN_PCI_BIT);
++DEFINE_TIMER (power_ramp_timer, ramp_power_on_leds, 0, 0);
 +
-+    // Setup the PCI clock divider
-+    {
-+    static const u32 PCIDIV_MASK = (((1UL << SYS_CTRL_CKCTRL_CTRL_PCIDIV_NUM_BITS) - 1) << SYS_CTRL_CKCTRL_CTRL_PCIDIV_BIT);
-+    *(volatile u32*)SYS_CTRL_CKCTRL_CTRL &= ~PCIDIV_MASK;
-+    *(volatile u32*)SYS_CTRL_CKCTRL_CTRL |= (PCI_CLOCK_DIVIDER << SYS_CTRL_CKCTRL_CTRL_PCIDIV_BIT);
-+    }
++enum { POWER_ON,
++      NUMBER_LEDS};
++      
++static struct platform_device *hipox_leds;    
++static u16 offset[NUMBER_LEDS] = {25};
 +
-+    // Enable clock to PCI core
-+    *(volatile u32*)SYS_CTRL_CKEN_SET_CTRL = (1UL << SYS_CTRL_CKEN_PCI_BIT);
++static u16 led [NUMBER_LEDS];
 +
-+    // Enable auto-arbitration between static and PCI
-+    *(u32*)SYS_CTRL_PCI_CTRL1 &= ~(1UL << SYSCTL_PCI_CTRL1_SYSPCI_STATIC_REQ);
++#define MAX_BRIGHTNESS   255
 +
-+    // Enable primary function on PCI clock line to be looped back
-+    writel(readl(PCI_CLOCK_PRISEL_REG) | PCI_CLOCK_MASK, PCI_CLOCK_PRISEL_REG);
++static void set_led(u16 led, u16 value)
++{
++      u16 led_index = offset[led] % MAX_PWMS;
++      
++      writel(value, (PWM_DATA_REGISTER_BASE+4*led_index));
++      
++}
 +
-+    // Enable GPIO output on PCI clock line to be looped back
-+    writel(PCI_CLOCK_MASK, PCI_CLOCK_SET_OE_REG);
++static void ramp_power_on_leds(unsigned long data)
++{
++      if (led[POWER_ON] < MAX_BRIGHTNESS) {
++               set_led(POWER_ON, ++led[POWER_ON]);
++               mod_timer(&power_ramp_timer, (power_ramp_timer.expires + msecs_to_jiffies(64)) );
++      }
++      else del_timer(&power_ramp_timer);
++}
 +
-+#ifdef CONFIG_HIPOX_PCI_RESET
-+    // Disable primary, secondary and teriary GPIO functions on PCI reset line
-+    writel(readl(PCI_RESET_PRISEL_REG) & ~PCI_RESET_MASK, PCI_RESET_PRISEL_REG);
-+    writel(readl(PCI_RESET_SECSEL_REG) & ~PCI_RESET_MASK, PCI_RESET_SECSEL_REG);
-+    writel(readl(PCI_RESET_TERSEL_REG) & ~PCI_RESET_MASK, PCI_RESET_TERSEL_REG);
++static void hipoxled_power_on_set(struct led_classdev *led_cdev, enum led_brightness value)
++{
++      if (value == 0) {
++              current_bright = 0;
++              led[POWER_ON]=0;
++          set_led(POWER_ON, 0);
++              
++      }
++      else
++      {
++              power_ramp_timer.expires = jiffies + msecs_to_jiffies(64);
++              add_timer(&power_ramp_timer);
++      }
++}
 +
-+    // Assert PCI reset from GPIO line
-+    writel(PCI_RESET_MASK, PCI_RESET_OUTPUT_CLR_REG);
++static struct led_classdev hipox_power_on_led = {
++      .name                   = "hipox:power_on",
++      .brightness_set         = hipoxled_power_on_set,
++};
 +
-+    // Enable GPIO output on PCI reset line
-+    writel(PCI_RESET_MASK, PCI_RESET_SET_OE_REG);
 +
-+    // Wait awhile for PCI reset to take effect
-+    mdelay(100);
++#ifdef CONFIG_PM
 +
-+    // Deassert PCI reset from GPIO line
-+    writel(PCI_RESET_MASK, PCI_RESET_OUTPUT_SET_REG);
-+#endif // CONFIG_HIPOX_PCI_RESET
-+#endif // CONFIG_PCI
++// TODO implement led suspend operation on NAS
++static int hipoxled_suspend(struct platform_device *dev, pm_message_t state)
++{
++#ifdef CONFIG_LEDS_TRIGGERS
++      if (hipox_amber_led.trigger && strcmp(hipox_amber_led.trigger->name, "sharpsl-charge"))
++#endif
++              led_classdev_suspend(&hipox_amber_led);
++      led_classdev_suspend(&hipox_green_led);
++      return 0;
++}
++// TODO implement led resume operation on NAS
++static int hipoxled_resume(struct platform_device *dev)
++{
++      led_classdev_resume(&hipox_amber_led);
++      led_classdev_resume(&hipox_green_led);
++      return 0;
++}
++#endif
 +
-+#ifdef CONFIG_HIPOX_SATA_POWER_1
-+    // Disable primary, secondary and teriary GPIO functions on SATA 1 power line
-+    writel(readl(SATA_POWER_1_PRISEL_REG) & ~SATA_POWER_1_MASK, SATA_POWER_1_PRISEL_REG);
-+    writel(readl(SATA_POWER_1_SECSEL_REG) & ~SATA_POWER_1_MASK, SATA_POWER_1_SECSEL_REG);
-+    writel(readl(SATA_POWER_1_TERSEL_REG) & ~SATA_POWER_1_MASK, SATA_POWER_1_TERSEL_REG);
++static int hipoxled_probe(struct platform_device *pdev)
++{
++      int ret;
++      int i;
 +
-+    // Enable power to SATA 1
-+    writel(SATA_POWER_1_MASK, SATA_POWER_1_OUTPUT_SET_REG);
++      writel(PWM_PERIOD, PWM_CLOCK_REGISTER);
 +
-+    // Enable GPIO output on SATA 1 power line
-+    writel(SATA_POWER_1_MASK, SATA_POWER_1_SET_OE_REG);
-+#endif // CONFIG_HIPOX_SATA_POWER_1
++      
++      /* enable PWM drives outputs */
++      for (i=0; i < NUMBER_LEDS ; ++i)
++      {
++              if (offset[i] < 32) {
++                      writel(readl(SYS_CTRL_GPIO_PWMSEL_CTRL_0) | (1 << offset[i]), SYS_CTRL_GPIO_PWMSEL_CTRL_0); 
++              }
++              else {
++                      writel(readl(SYS_CTRL_GPIO_PWMSEL_CTRL_1) | (1 << (offset[i]% 32)), SYS_CTRL_GPIO_PWMSEL_CTRL_1);
++              }
++      }
 +
-+#ifdef CONFIG_HIPOX_SATA_POWER_2
-+    // Disable primary, secondary and teriary GPIO functions on SATA 2 power line
-+    writel(readl(SATA_POWER_2_PRISEL_REG) & ~SATA_POWER_2_MASK, SATA_POWER_2_PRISEL_REG);
-+    writel(readl(SATA_POWER_2_SECSEL_REG) & ~SATA_POWER_2_MASK, SATA_POWER_2_SECSEL_REG);
-+    writel(readl(SATA_POWER_2_TERSEL_REG) & ~SATA_POWER_2_MASK, SATA_POWER_2_TERSEL_REG);
++      ret = led_classdev_register(&pdev->dev, &hipox_power_on_led);
++      
++      if (ret < 0) goto error_1;
++      
++      return ret;
++      
++error_1:              
++      return ret;
++}
 +
-+    // Enable power to SATA 2
-+    writel(SATA_POWER_2_MASK, SATA_POWER_2_OUTPUT_SET_REG);
++static int hipoxled_remove(struct platform_device *pdev)
++{
++      int i;
++      
++      led_classdev_unregister(&hipox_power_on_led);
 +
-+    // Enable GPIO output on SATA 2 power line
-+    writel(SATA_POWER_2_MASK, SATA_POWER_2_SET_OE_REG);
-+#endif // CONFIG_HIPOX_SATA_POWER_2
++      /* disable PWM drives outputs */
++      for (i=0; i < NUMBER_LEDS ; ++i)
++      {
++              if (offset[i] < 32) {
++                      writel(readl(SYS_CTRL_GPIO_PWMSEL_CTRL_0) & ~((u32)1 << offset[i]), SYS_CTRL_GPIO_PWMSEL_CTRL_0); 
++              }
++              else {
++                      writel(readl(SYS_CTRL_GPIO_PWMSEL_CTRL_1) & ~((u32)1 << (offset[i]% 32)), SYS_CTRL_GPIO_PWMSEL_CTRL_1);
++              }
++      }
++      
++      writel(PWM_CLOCK_REGISTER, 0);
++      
++      return 0;
++}
 +
-+#ifdef CONFIG_HIPOX_INSTRUMENT_COPIES_GPIO
-+    // Use GPIO 6 (normally PCI Req 6) for copies instrumentation
-+    #define INSTRUMENT_COPIES_GPIO_MASK ((1UL << 6) | (1UL << 7))
 +
-+    // Enable normal GPIO on line
-+    writel(readl(SYS_CTRL_GPIO_PRIMSEL_CTRL_0) & ~INSTRUMENT_COPIES_GPIO_MASK, SYS_CTRL_GPIO_PRIMSEL_CTRL_0);
-+    writel(readl(SYS_CTRL_GPIO_SECSEL_CTRL_0)  & ~INSTRUMENT_COPIES_GPIO_MASK, SYS_CTRL_GPIO_SECSEL_CTRL_0);
-+    writel(readl(SYS_CTRL_GPIO_TERTSEL_CTRL_0) & ~INSTRUMENT_COPIES_GPIO_MASK, SYS_CTRL_GPIO_TERTSEL_CTRL_0);
++static struct platform_driver hipoxled_driver = {
++      .probe          = hipoxled_probe,
++      .remove         = hipoxled_remove,
++#ifdef CONFIG_PM
++      .suspend        = hipoxled_suspend,
++      .resume         = hipoxled_resume,
++#endif
++      .driver         = {
++              .name           = "hipox-leds",
++              .owner      = THIS_MODULE,
++      },
++};
 +
-+    // Set line inactive to begin with
-+    writel(INSTRUMENT_COPIES_GPIO_MASK, GPIO_A_OUTPUT_CLEAR);
++static int __init hipoxled_init(void)
++{
++      int ret;
 +
-+    // Enable line as an output
-+    writel(INSTRUMENT_COPIES_GPIO_MASK, GPIO_A_OUTPUT_ENABLE_SET);
-+#endif // CONFIG_HIPOX_INSTRUMENT_COPIES_GPIO
++      ret = platform_driver_register(&hipoxled_driver);
++      
++      
++      
++      /* now register the devices on the bus so they can be associated with the driver */
++      if (!ret) 
++                      hipox_leds=platform_device_register_simple("hipox-leds", -1, NULL, 0);
++      return ret;
++}
 +
-+#ifdef CONFIG_HIPOX_USB_CKOUT
-+    // Enable secondary function (USB clock out) on GPIO 10
-+    writel(readl(SYS_CTRL_GPIO_PRIMSEL_CTRL_0) & ~(1UL << 10), SYS_CTRL_GPIO_PRIMSEL_CTRL_0);
-+    writel(readl(SYS_CTRL_GPIO_SECSEL_CTRL_0)  |  (1UL << 10), SYS_CTRL_GPIO_SECSEL_CTRL_0);
-+#endif // CONFIG_HIPOX_USB_CKOUT
++static void __exit hipoxled_exit(void)
++{
++      if (hipox_leds) {
++              platform_device_unregister(hipox_leds);
++      }
 +
-+#ifdef CONFIG_HIPOX_USB_HUB_RESET_CONTROL
-+    // Disable primary, secondary and teriary GPIO functions on USB hub reset control line
-+    writel(readl(USB_HUB_RESET_PRISEL_REG) & ~USB_HUB_RESET_MASK, USB_HUB_RESET_PRISEL_REG);
-+    writel(readl(USB_HUB_RESET_SECSEL_REG) & ~USB_HUB_RESET_MASK, USB_HUB_RESET_SECSEL_REG);
-+    writel(readl(USB_HUB_RESET_TERSEL_REG) & ~USB_HUB_RESET_MASK, USB_HUB_RESET_TERSEL_REG);
++      platform_driver_unregister(&hipoxled_driver);
++}
 +
-+#ifdef CONFIG_HIPOX_USB_HUB_RESET_TOGGLE
-+      // Assert USB hub reset
-+      writel(USB_HUB_RESET_MASK, CONFIG_HIPOX_USB_HUB_RESET_ACTIVE_HIGH ? USB_HUB_RESET_OUTPUT_SET_REG : USB_HUB_RESET_OUTPUT_CLR_REG);
-+#else
-+      // Deassert USB hub reset
-+      writel(USB_HUB_RESET_MASK, CONFIG_HIPOX_USB_HUB_RESET_ACTIVE_HIGH ? USB_HUB_RESET_OUTPUT_CLR_REG : USB_HUB_RESET_OUTPUT_SET_REG);
-+#endif // CONFIG_HIPOX_USB_HUB_RESET_TOGGLE
++module_init(hipoxled_init);
++module_exit(hipoxled_exit);
 +
-+    // Enable GPIO output on USB hub reset line
-+    writel(USB_HUB_RESET_MASK, USB_HUB_RESET_SET_OE_REG);
++MODULE_AUTHOR("John Larkworthy <john.larkworthy@oxsem.com");
++MODULE_DESCRIPTION("HIPOX front panel LED driver");
++MODULE_LICENSE("GPL");
+diff -Nurd linux-2.6.24.4/arch/arm/mach-hipox/ledtrig_sata.c linux-2.6.24/arch/arm/mach-hipox/ledtrig_sata.c
+--- linux-2.6.24.4/arch/arm/mach-hipox/ledtrig_sata.c  1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/mach-hipox/ledtrig_sata.c    2010-01-14 14:01:15.000000000 +0100
+@@ -0,0 +1,69 @@
++/*
++ * linux/arch/arm/mach-hipox/leds.c
++ *
++ * Copyright (C) 2006 Oxford Semiconductor Ltd
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
 +
-+#ifdef CONFIG_HIPOX_USB_HUB_RESET_TOGGLE
-+      if (CONFIG_HIPOX_USB_HUB_RESET_PERIOD_MS > 0) {
-+              // Wait for USB hub reset toggle assertion time
-+              mdelay(CONFIG_HIPOX_USB_HUB_RESET_PERIOD_MS);
-+      }
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/timer.h>
++#include <linux/leds.h>
 +
-+      // Deassert USB hub reset
-+      writel(USB_HUB_RESET_MASK, CONFIG_HIPOX_USB_HUB_RESET_ACTIVE_HIGH ? USB_HUB_RESET_OUTPUT_CLR_REG : USB_HUB_RESET_OUTPUT_SET_REG);
-+#endif // CONFIG_HIPOX_USB_HUB_RESET_TOGGLE
++static void ledtrig_ide_timerfunc(unsigned long data);
 +
-+#endif // CONFIG_HIPOX_USB_HUB_RESET_CONTROL
-+}
++DEFINE_LED_TRIGGER(ledtrig_ide);
++static DEFINE_TIMER(ledtrig_ide_timer, ledtrig_ide_timerfunc, 0, 0);
++static int ide_activity;
++static int ide_lastactivity;
 +
-+static void __init hipox_fixup(
-+    struct machine_desc *desc,
-+    struct tag *tags,
-+    char **cmdline,
-+    struct meminfo *mi)
++void ledtrig_sata_activity(void)
 +{
++      ide_activity++;
++      if (!timer_pending(&ledtrig_ide_timer))
++              mod_timer(&ledtrig_ide_timer, jiffies + msecs_to_jiffies(10));
++}
++EXPORT_SYMBOL(ledtrig_sata_activity);
 +
-+    mi->nr_banks = 0;
-+    mi->bank[mi->nr_banks].start = SDRAM_PA;
-+    mi->bank[mi->nr_banks].size  = SDRAM_SIZE;
-+    mi->bank[mi->nr_banks].node = mi->nr_banks;
-+    ++mi->nr_banks;
-+#ifdef CONFIG_DISCONTIGMEM
-+    mi->bank[mi->nr_banks].start = SRAM_PA;
-+    mi->bank[mi->nr_banks].size  = SRAM_SIZE;
-+#ifdef LEON_IMAGE_IN_SRAM
-+    mi->bank[mi->nr_banks].size -= LEON_IMAGE_SIZE;
-+#endif
-+    mi->bank[mi->nr_banks].node = mi->nr_banks;
-+    ++mi->nr_banks;
-+#endif
-+
-+//printk(KERN_NOTICE "%d memory %s\n", mi->nr_banks, (mi->nr_banks > 1) ? "regions" : "region");
++static void ledtrig_ide_timerfunc(unsigned long data)
++{
++      if (ide_lastactivity != ide_activity) {
++              ide_lastactivity = ide_activity;
++              led_trigger_event(ledtrig_ide, LED_FULL);
++              mod_timer(&ledtrig_ide_timer, jiffies + msecs_to_jiffies(10));
++      } else {
++              led_trigger_event(ledtrig_ide, LED_OFF);
++      }
 +}
 +
-+#ifdef CONFIG_DO_MEM_TEST
-+static void __init hipox_asm_copy(void* dst, void* src, u32 length)
++static int __init ledtrig_ide_init(void)
 +{
-+    // Assume the length is consistent with transfering 8 quads per load/store
-+    asm volatile(
-+        "1:ldmia %0!, {r3, r4, r5, r6, r7, r8, r9, r12};"
-+        "subs %2, %2, #32;"
-+        "stmia %1!, {r3, r4, r5, r6, r7, r8, r9, r12};"
-+        "bne 1b;"
-+        :
-+        : "r" (src), "r" (dst), "r" (length)
-+        : "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r12");
++      led_trigger_register_simple("sata-disk", &ledtrig_ide);
++      return 0;
 +}
 +
-+static void __init hipox_mem_test(void)
++static void __exit ledtrig_ide_exit(void)
 +{
-+    static const unsigned BUFFER_SIZE_CHARS = 16*1024;
-+    static const unsigned BUFFER_ELEMENTS = (BUFFER_SIZE_CHARS / sizeof(unsigned long));
++      led_trigger_unregister_simple(ledtrig_ide);
++}
 +
-+    dma_addr_t dma_address;
-+    unsigned long* buffer;
++module_init(ledtrig_ide_init);
++module_exit(ledtrig_ide_exit);
 +
-+    buffer = dma_alloc_coherent(0, BUFFER_SIZE_CHARS, &dma_address, GFP_KERNEL | GFP_DMA);
-+    if (!buffer) {
-+        printk(KERN_ERR "$RFailed to allocate ucached/unbuffered memory test buffer\n");
-+    } else {
-+        static const int ITERATIONS = 10;
++MODULE_AUTHOR("John Larkworthy <john.larkworthy@hipox.com>");
++MODULE_DESCRIPTION("LED SATA Disk Activity Trigger");
++MODULE_LICENSE("GPL");
+diff -Nurd linux-2.6.24.4/arch/arm/mach-hipox/leon.c linux-2.6.24/arch/arm/mach-hipox/leon.c
+--- linux-2.6.24.4/arch/arm/mach-hipox/leon.c  1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/mach-hipox/leon.c    2010-01-14 14:01:15.000000000 +0100
+@@ -0,0 +1,244 @@
++/*
++ * linux/arch/arm/mach-hipox/leon.c
++ *
++ * Copyright (C) 2005 Oxford Semiconductor Ltd
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++#ifdef CONFIG_SUPPORT_LEON
 +
-+        unsigned long* buf1 = buffer;
-+        unsigned long* buf2 = buffer + (BUFFER_ELEMENTS/2);
-+        int j;
-+        u32* time1 = (u32*)kmalloc(ITERATIONS *sizeof(u32), GFP_KERNEL);
-+        u32* time2 = (u32*)kmalloc(ITERATIONS *sizeof(u32), GFP_KERNEL);
++#include <asm/io.h>
++#include <asm/types.h>
++#include <asm/arch/hardware.h>
++#include <linux/ctype.h>
++#include <linux/delay.h>
++#include <linux/dma-mapping.h>
++#include <linux/errno.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/kernel.h>
++#include <linux/slab.h>
++#include <asm/arch/leon.h>
 +
-+        BUG_ON(!time1 || !time2);
-+        
-+        printk("Uncached/unbuffered: src = 0x%08x, dst = 0x%08x, length = %u, elements = %u, dma_address = 0x%08x\n", (u32)buf1, (u32)buf2, BUFFER_SIZE_CHARS/2, BUFFER_ELEMENTS/2, dma_address);
++static u8 asciihex_to_decimal(u8 ascii)
++{
++    return isdigit(ascii) ? (ascii - '0') : (isalpha(ascii) ? ((toupper(ascii) - 'A') + 10)  : 0);
++}
 +
-+        printk("\nAll accesses:\n");
-+        init_ahb_monitors(AHB_MON_HWRITE_READS_AND_WRITES, 0, 0, 0, 0);
++static u8 srec_read_u8(const s8** srec)
++{
++    u8 first_ascii  = **srec;
++    u8 second_ascii = *++*srec;
++    ++*srec;
++    return ((asciihex_to_decimal(first_ascii) << 4) | asciihex_to_decimal(second_ascii));
++}
 +
-+        for (j=0; j < ITERATIONS; j++) {
-+            unsigned long* src = buf1;
-+            unsigned long* dst = buf2;
-+//            int i;
++static u32 srec_read_u32(const s8** srec)
++{
++    u32 word  = ((u32)srec_read_u8(srec) << 24);
++    word     |= ((u32)srec_read_u8(srec) << 16);
++    word     |= ((u16)srec_read_u8(srec) << 8);
++    word     |= srec_read_u8(srec);
++    return word;
++}
 +
-+            time1[j] = readl(TIMER2_VALUE);
-+//            memcpy(dst, src, BUFFER_SIZE_CHARS/2);
-+            hipox_asm_copy(dst, src, BUFFER_SIZE_CHARS/2);
-+//            for (i=0; i<BUFFER_ELEMENTS/2; i++) {
-+//                *dst++ = *src++;
-+//            }
-+            time2[j] = readl(TIMER2_VALUE);
-+        }
-+        read_ahb_monitors();
-+        for (j=0; j < ITERATIONS; j++) {
-+            printk("%u->%lu Bytes/s\n", time1[j]-time2[j], 100000UL * (BUFFER_SIZE_CHARS/2) / (time1[j]-time2[j]));
-+        }
++static void skip_to_next_record(const s8** srec)
++{
++    while (*++*srec != '\n');
++    ++*srec;
++}
 +
-+        printk("\nNon-burst accesses:\n");
-+        init_ahb_monitors(AHB_MON_HWRITE_READS_AND_WRITES, ~0, AHB_MON_HBURST_SINGLE, 0, 0);
-+        for (j=0; j < ITERATIONS; j++) {
-+            unsigned long* src = buf1;
-+            unsigned long* dst = buf2;
-+//            int i;
++/**
++ * @param  srec An const s8** pointing to the position in the input s-record
++ *         array at which to begin parsing
++ * @param  buf An u8* into which any extracted record in to be placed
++ * @param  adr An u8** into which either the extracted record's load address is
++ *         to be written, or the execution start address
++ * @param  len An u8* into which the length in bytes of the extracted record is
++ *         to be written
++ * @return An int which is zero if another record is available, else if non-zero
++ *         indicated that the execution start address is available in the
++ *         adr argument
++ */
++static void read_record(u8 len, const s8** srec, u8* buf)
++{
++    int quads = len/sizeof(u32);
++    int spare = len - (quads*sizeof(u32));
 +
-+            time1[j] = readl(TIMER2_VALUE);
-+//            memcpy(dst, src, BUFFER_SIZE_CHARS/2);
-+            hipox_asm_copy(dst, src, BUFFER_SIZE_CHARS/2);
-+//            for (i=0; i<BUFFER_ELEMENTS/2; i++) {
-+//                *dst++ = *src++;
-+//            }
-+            time2[j] = readl(TIMER2_VALUE);
-+        }
-+        read_ahb_monitors();
-+        for (j=0; j < ITERATIONS; j++) {
-+            printk("%u->%lu Bytes/s\n", time1[j]-time2[j], 100000UL * (BUFFER_SIZE_CHARS/2) / (time1[j]-time2[j]));
-+        }
++    int i=0;
++    while (i < quads) {
++        ((u32*)buf)[i++] = srec_read_u32(srec);
++    }
++    i = len-spare;
++    while (i < len) {
++        buf[i++] = srec_read_u8(srec);
++    }
++}
 +
-+        printk("\nINCR accesses:\n");
-+        init_ahb_monitors(AHB_MON_HWRITE_READS_AND_WRITES, ~0, AHB_MON_HBURST_INCR, 0, 0);
-+        for (j=0; j < ITERATIONS; j++) {
-+            unsigned long* src = buf1;
-+            unsigned long* dst = buf2;
-+//            int i;
++static int get_next_record(const s8** srec, u8* buf, u8** adr, u8* len)
++{
++    int again;
++    int last = 1;
 +
-+            time1[j] = readl(TIMER2_VALUE);
-+//            memcpy(dst, src, BUFFER_SIZE_CHARS/2);
-+            hipox_asm_copy(dst, src, BUFFER_SIZE_CHARS/2);
-+//            for (i=0; i<BUFFER_ELEMENTS/2; i++) {
-+//                *dst++ = *src++;
-+//            }
-+            time2[j] = readl(TIMER2_VALUE);
-+        }
-+        read_ahb_monitors();
-+        for (j=0; j < ITERATIONS; j++) {
-+            printk("%u->%lu Bytes/s\n", time1[j]-time2[j], 100000UL * (BUFFER_SIZE_CHARS/2) / (time1[j]-time2[j]));
++    *adr = 0;
++    do {
++        again = 0;
++        if (**srec == 'S') {
++            switch (*++*srec) {
++                case '0':
++                    skip_to_next_record(srec);
++                    again = 1;
++                    break;
++                case '3':
++                    ++*srec;
++                    *len = srec_read_u8(srec) - sizeof(u32) - 1;
++                    *adr = (u8*)srec_read_u32(srec);
++                    read_record(*len, srec, buf);
++                    skip_to_next_record(srec);
++                    last = 0;
++                    break;
++                case '7':
++                    ++*srec;
++                    *len = srec_read_u8(srec) - 1;
++                    if (*len >= sizeof(u32)) {
++                        *adr = (u8*)srec_read_u32(srec);
++                    }
++                    break;
++                default:
++                    break;
++            }
 +        }
++    } while (again);
 +
-+        printk("\nWRAP4 accesses:\n");
-+        init_ahb_monitors(AHB_MON_HWRITE_READS_AND_WRITES, ~0, AHB_MON_HBURST_WRAP4, 0, 0);
-+        for (j=0; j < ITERATIONS; j++) {
-+            unsigned long* src = buf1;
-+            unsigned long* dst = buf2;
-+//            int i;
++    return last;
++}
 +
-+            time1[j] = readl(TIMER2_VALUE);
-+//            memcpy(dst, src, BUFFER_SIZE_CHARS/2);
-+            hipox_asm_copy(dst, src, BUFFER_SIZE_CHARS/2);
-+//            for (i=0; i<BUFFER_ELEMENTS/2; i++) {
-+//                *dst++ = *src++;
-+//            }
-+            time2[j] = readl(TIMER2_VALUE);
-+        }
-+        read_ahb_monitors();
-+        for (j=0; j < ITERATIONS; j++) {
-+            printk("%u->%lu Bytes/s\n", time1[j]-time2[j], 100000UL * (BUFFER_SIZE_CHARS/2) / (time1[j]-time2[j]));
-+        }
++static const u32 ENDIAN_LITTLE_READ_BIT = 30;
++static const u32 ENDIAN_BIG_WRITE_BIT   = 31;
 +
-+        printk("\nINCR4 accesses:\n");
-+        init_ahb_monitors(AHB_MON_HWRITE_READS_AND_WRITES, ~0, AHB_MON_HBURST_INCR4, 0, 0);
-+        for (j=0; j < ITERATIONS; j++) {
-+            unsigned long* src = buf1;
-+            unsigned long* dst = buf2;
-+//            int i;
++static u8* convert_adr_to_virt(u8* adr)
++{
++      static const u32 ARM_HIGH_ORDER_ADR_BIT = 30;
 +
-+            time1[j] = readl(TIMER2_VALUE);
-+//            memcpy(dst, src, BUFFER_SIZE_CHARS/2);
-+            hipox_asm_copy(dst, src, BUFFER_SIZE_CHARS/2);
-+//            for (i=0; i<BUFFER_ELEMENTS/2; i++) {
-+//                *dst++ = *src++;
-+//            }
-+            time2[j] = readl(TIMER2_VALUE);
-+        }
-+        read_ahb_monitors();
-+        for (j=0; j < ITERATIONS; j++) {
-+            printk("%u->%lu Bytes/s\n", time1[j]-time2[j], 100000UL * (BUFFER_SIZE_CHARS/2) / (time1[j]-time2[j]));
-+        }
++    u32 virt = (u32)adr;
 +
-+        printk("\nWRAP8 accesses:\n");
-+        init_ahb_monitors(AHB_MON_HWRITE_READS_AND_WRITES, ~0, AHB_MON_HBURST_WRAP8, 0, 0);
-+        for (j=0; j < ITERATIONS; j++) {
-+            unsigned long* src = buf1;
-+            unsigned long* dst = buf2;
-+//            int i;
++      // Zero the Leon endian control bits
++      virt &= ~((1UL << ENDIAN_BIG_WRITE_BIT) | (1UL << ENDIAN_LITTLE_READ_BIT));
 +
-+            time1[j] = readl(TIMER2_VALUE);
-+//            memcpy(dst, src, BUFFER_SIZE_CHARS/2);
-+            hipox_asm_copy(dst, src, BUFFER_SIZE_CHARS/2);
-+//            for (i=0; i<BUFFER_ELEMENTS/2; i++) {
-+//                *dst++ = *src++;
-+//            }
-+            time2[j] = readl(TIMER2_VALUE);
-+        }
-+        read_ahb_monitors();
-+        for (j=0; j < ITERATIONS; j++) {
-+            printk("%u->%lu Bytes/s\n", time1[j]-time2[j], 100000UL * (BUFFER_SIZE_CHARS/2) / (time1[j]-time2[j]));
-+        }
++      // Convert to an ARM physical address
++      virt |= (1UL << ARM_HIGH_ORDER_ADR_BIT);
 +
-+        printk("\nINCR8 accesses:\n");
-+        init_ahb_monitors(AHB_MON_HWRITE_READS_AND_WRITES, ~0, AHB_MON_HBURST_INCR8, 0, 0);
-+        for (j=0; j < ITERATIONS; j++) {
-+            unsigned long* src = buf1;
-+            unsigned long* dst = buf2;
-+//            int i;
++    // Is address sane?
++    if (virt < LEON_IMAGE_BASE_PA) {
++        panic("CoPro SRAM load address 0x%08x below mapped region beginning at 0x%08lx\n", (u32)adr, LEON_IMAGE_BASE_PA);
++    } else {
++        virt -= LEON_IMAGE_BASE_PA;
++        virt += LEON_IMAGE_BASE;
++    }
 +
-+            time1[j] = readl(TIMER2_VALUE);
-+//            memcpy(dst, src, BUFFER_SIZE_CHARS/2);
-+            hipox_asm_copy(dst, src, BUFFER_SIZE_CHARS/2);
-+//            for (i=0; i<BUFFER_ELEMENTS/2; i++) {
-+//                *dst++ = *src++;
-+//            }
-+            time2[j] = readl(TIMER2_VALUE);
-+        }
-+        read_ahb_monitors();
-+        for (j=0; j < ITERATIONS; j++) {
-+            printk("%u->%lu Bytes/s\n", time1[j]-time2[j], 100000UL * (BUFFER_SIZE_CHARS/2) / (time1[j]-time2[j]));
-+        }
++    return (u8*)virt;
++}
 +
-+        printk("\nWRAP16 accesses:\n");
-+        init_ahb_monitors(AHB_MON_HWRITE_READS_AND_WRITES, ~0, AHB_MON_HBURST_WRAP16, 0, 0);
-+        for (j=0; j < ITERATIONS; j++) {
-+            unsigned long* src = buf1;
-+            unsigned long* dst = buf2;
-+//            int i;
++static void leon_load_image(const s8 *srec)
++{
++    u8       *buf;
++    u8       *adr;
++    u8        len;
++    u32       code_base;
 +
-+            time1[j] = readl(TIMER2_VALUE);
-+//            memcpy(dst, src, BUFFER_SIZE_CHARS/2);
-+            hipox_asm_copy(dst, src, BUFFER_SIZE_CHARS/2);
-+//            for (i=0; i<BUFFER_ELEMENTS/2; i++) {
-+//                *dst++ = *src++;
-+//            }
-+            time2[j] = readl(TIMER2_VALUE);
-+        }
-+        read_ahb_monitors();
-+        for (j=0; j < ITERATIONS; j++) {
-+            printk("%u->%lu Bytes/s\n", time1[j]-time2[j], 100000UL * (BUFFER_SIZE_CHARS/2) / (time1[j]-time2[j]));
-+        }
++    // Copy each record to the specified address
++    // Convert the LEON physical address to an ARM virtual address before
++      // attempting to get the ARM to access it
++    // NB must endian-swap any trailing non-quad multiple bytes, as LEON will
++    // expect its instruction data in big endian format, whereas the ARM is
++    // little endian
++    buf  = kmalloc(512, GFP_KERNEL);
++    while (!get_next_record(&srec, buf, &adr, &len)) {
++        int i=0;
++        int quads = len/sizeof(u32);
++        int spare = len - (quads*sizeof(u32));
++        int padded_len = len+(sizeof(u32)-spare);
++        u32* quad_ptr;
 +
-+        printk("\nINCR16 accesses:\n");
-+        init_ahb_monitors(AHB_MON_HWRITE_READS_AND_WRITES, ~0, AHB_MON_HBURST_INCR16, 0, 0);
-+        for (j=0; j < ITERATIONS; j++) {
-+            unsigned long* src = buf1;
-+            unsigned long* dst = buf2;
-+//            int i;
++        adr = convert_adr_to_virt(adr);
 +
-+            time1[j] = readl(TIMER2_VALUE);
-+//            memcpy(dst, src, BUFFER_SIZE_CHARS/2);
-+            hipox_asm_copy(dst, src, BUFFER_SIZE_CHARS/2);
-+//            for (i=0; i<BUFFER_ELEMENTS/2; i++) {
-+//                *dst++ = *src++;
-+//            }
-+            time2[j] = readl(TIMER2_VALUE);
++        quad_ptr = (u32*)adr;
++        while (i < quads) {
++            *quad_ptr++ = ((u32*)buf)[i++];
 +        }
-+        read_ahb_monitors();
-+        for (j=0; j < ITERATIONS; j++) {
-+            printk("%u->%lu Bytes/s\n", time1[j]-time2[j], 100000UL * (BUFFER_SIZE_CHARS/2) / (time1[j]-time2[j]));
++        adr = (u8*)quad_ptr;
++        for (i=len; i < padded_len; i++) {
++            buf[i] = 0;
++        }
++        i = padded_len-1;
++        while (i >= (len-spare)) {
++            *adr++ = buf[i--];
 +        }
-+
-+        dma_free_coherent(0, BUFFER_SIZE_CHARS, buffer, dma_address);
-+
-+        kfree(time1);
-+        kfree(time2);
 +    }
++    kfree(buf);
 +
-+    buffer = kmalloc(BUFFER_SIZE_CHARS, GFP_KERNEL | GFP_DMA);
-+    if (!buffer) {
-+        printk(KERN_ERR "$RFailed to allocate cached memory test buffer\n");
-+    } else {
-+        static const int ITERATIONS = 100;
-+
-+        unsigned long* buf1 = buffer;
-+        unsigned long* buf2 = buffer + (BUFFER_ELEMENTS/2);
-+        unsigned long* src = buf1;
-+        unsigned long* dst = buf2;
-+        int j;
-+        u32* time1 = (u32*)kmalloc(ITERATIONS *sizeof(u32), GFP_KERNEL);
-+        u32* time2 = (u32*)kmalloc(ITERATIONS *sizeof(u32), GFP_KERNEL);
++    // Start LEON execution at the address specified by the S-records, with
++    // correct endianess. Use the address unchanged, as the LEON required
++    // physical addresses and may make use of alternative upper nibble values
++    code_base = (((u32)adr & ~((1UL << ENDIAN_BIG_WRITE_BIT) | (1UL << ENDIAN_LITTLE_READ_BIT))) | (1UL << ENDIAN_BIG_WRITE_BIT));
 +
-+        BUG_ON(!time1 || !time2);
++    // Set the LEON's start address
++    printk(KERN_NOTICE "CoPro: Programming start address as 0x%08x (basic adr = 0x%08x)\n", code_base, (u32)adr);
++    writel(code_base, SYS_CTRL_COPRO_CTRL);
 +
-+        printk("Cached/: src = 0x%08x, dst = 0x%08x, length = %u, elements = %u\n", (u32)buf1, (u32)buf2, BUFFER_SIZE_CHARS/2, BUFFER_ELEMENTS/2);
++    // Ensure start address has been loaded before release the LEON from reset
++    wmb();
++}
 +
-+        init_ahb_monitors(AHB_MON_HWRITE_READS_AND_WRITES, 0, 0, 0, 0);
++void init_copro(const s8 *srec, unsigned long arg)
++{
++    // Ensure the LEON is in reset
++    writel(1UL << SYS_CTRL_RSTEN_COPRO_BIT, SYS_CTRL_RSTEN_SET_CTRL);
 +
-+        // Measure the first cached iteration separately
-+        printk("1st iteration:\n");
-+        restart_ahb_monitors();
-+        time1[0] = readl(TIMER2_VALUE);
-+//            memcpy(dst, src, BUFFER_SIZE_CHARS/2);
-+        hipox_asm_copy(dst, src, BUFFER_SIZE_CHARS/2);
-+//            for (i=0; i<BUFFER_ELEMENTS/2; i++) {
-+//                *dst++ = *src++;
-+//            }
-+        time2[0] = readl(TIMER2_VALUE);
-+        read_ahb_monitors();
-+        printk("%u->%lu Bytes/s\n", time1[0]-time2[0], 100000UL * (BUFFER_SIZE_CHARS/2) / (time1[0]-time2[0]));
++    // Enable the clock to the LEON
++    writel(1UL << SYS_CTRL_CKEN_COPRO_BIT, SYS_CTRL_CKEN_SET_CTRL);
 +
-+        printk("Subsequent iterations:\n");
-+        restart_ahb_monitors();
-+        for (j=1; j < ITERATIONS; j++) {
-+            src = buf1;
-+            dst = buf2;
-+//            int i;
++    // Ensure reset and clock operations are complete
++    wmb();
 +
-+            time1[j] = readl(TIMER2_VALUE);
-+//            memcpy(dst, src, BUFFER_SIZE_CHARS/2);
-+            hipox_asm_copy(dst, src, BUFFER_SIZE_CHARS/2);
-+//            for (i=0; i<BUFFER_ELEMENTS/2; i++) {
-+//                *dst++ = *src++;
-+//            }
-+            time2[j] = readl(TIMER2_VALUE);
-+        }
-+        read_ahb_monitors();
++    // Place LEON context argument in top quad of SRAM
++      *((u32*)(LEON_IMAGE_BASE+LEON_IMAGE_SIZE-sizeof(u32))) = arg;
 +
-+        for (j=1; j < ITERATIONS; j++) {
-+            printk("%u->%lu Bytes/s\n", time1[j]-time2[j], 100000UL * (BUFFER_SIZE_CHARS/2) / (time1[j]-time2[j]));
-+        }
++    // Load LEON's program and data and execution start address
++    leon_load_image(srec);
 +
-+        kfree(time1);
-+        kfree(time2);
++    // Release the LEON from reset so it begins execution of the loaded code
++    writel(1UL << SYS_CTRL_RSTEN_COPRO_BIT, SYS_CTRL_RSTEN_CLR_CTRL);
 +
-+        kfree(buffer);
-+    }
++    // Give the LEON a chance to stabilise before giving it any commands
++    mdelay(100);
++    return;
 +}
-+#endif // CONFIG_DO_MEM_TEST
-+
-+#ifdef CONFIG_HIPOX_LED_TEST
-+
-+#define LED_D1  (1UL << 6)
-+#define LED_D2  (1UL << 7)
-+#define LED_D3  (1UL << 13)
-+#define LED_D4  (1UL << 14)
-+#define LED_D5  (1UL << 19)
-+#define LED_D6  (1UL << 21)
-+#define LED_D7  (1UL << 25)
-+#define LED_D8  (1UL << 26)
-+#define LED_D9  (1UL << 27)
-+#define FIRST_LEDS_MASK (LED_D1 | LED_D2 | LED_D3 | LED_D4 | LED_D5 | LED_D6 | LED_D7 | LED_D8 | LED_D9)
++EXPORT_SYMBOL_GPL(init_copro);
 +
-+#define LED_D10 (1UL << 1)
-+#define SECOND_LEDS_MASK (LED_D10)
++void shutdown_copro(void)
++{
++    // Ensure the LEON is in reset
++    writel(1UL << SYS_CTRL_RSTEN_COPRO_BIT, SYS_CTRL_RSTEN_SET_CTRL);
 +
-+#define PWM_MASK (1UL << 8)
++    // Disable the clock to the LEON
++    writel(1UL << SYS_CTRL_CKEN_COPRO_BIT, SYS_CTRL_CKEN_CLR_CTRL);
 +
-+static void test_leds_and_pwm(void)
-+{
-+    // Disable primary, secondary and teriary GPIO functions for first nine LEDS
-+    writel(readl(SYS_CTRL_GPIO_PRIMSEL_CTRL_0) & ~FIRST_LEDS_MASK, SYS_CTRL_GPIO_PRIMSEL_CTRL_0);
-+    writel(readl(SYS_CTRL_GPIO_SECSEL_CTRL_0)  & ~FIRST_LEDS_MASK, SYS_CTRL_GPIO_SECSEL_CTRL_0);
-+    writel(readl(SYS_CTRL_GPIO_TERTSEL_CTRL_0) & ~FIRST_LEDS_MASK, SYS_CTRL_GPIO_TERTSEL_CTRL_0);
++    // Ensure reset and clock operations are complete
++    wmb();
++}
++EXPORT_SYMBOL_GPL(shutdown_copro);
 +
-+    // Disable primary, secondary and teriary GPIO functions for last LED
-+    writel(readl(SYS_CTRL_GPIO_PRIMSEL_CTRL_1) & ~SECOND_LEDS_MASK, SYS_CTRL_GPIO_PRIMSEL_CTRL_1);
-+    writel(readl(SYS_CTRL_GPIO_SECSEL_CTRL_1)  & ~SECOND_LEDS_MASK, SYS_CTRL_GPIO_SECSEL_CTRL_1);
-+    writel(readl(SYS_CTRL_GPIO_TERTSEL_CTRL_1) & ~SECOND_LEDS_MASK, SYS_CTRL_GPIO_TERTSEL_CTRL_1);
++#endif // CONFIG_SUPPORT_LEON
+diff -Nurd linux-2.6.24.4/arch/arm/mach-hipox/Makefile linux-2.6.24/arch/arm/mach-hipox/Makefile
+--- linux-2.6.24.4/arch/arm/mach-hipox/Makefile        1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/mach-hipox/Makefile  2010-01-14 14:01:15.000000000 +0100
+@@ -0,0 +1,43 @@
++#
++# Makefile for the linux kernel.
++#
 +
-+    // Turn off first nine LEDs
-+    writel(FIRST_LEDS_MASK, GPIO_A_OUTPUT_SET);
++# Object file lists.
 +
-+    // Turn off tenth LED
-+    writel(SECOND_LEDS_MASK, GPIO_B_OUTPUT_SET);
++obj-y := hipox.o irq.o time.o dma.o pci.o ahb_mon.o leon.o samba_reserve.o
 +
-+    // Enable first nine LEDs as outputs
-+    writel(FIRST_LEDS_MASK, GPIO_A_OUTPUT_ENABLE_SET);
++obj-$(CONFIG_SYNOPSYS_GMAC) += gmac.o
 +
-+    // Enable tenth LED as output
-+    writel(SECOND_LEDS_MASK, GPIO_B_OUTPUT_ENABLE_SET);
++gmac-objs := gmac-napi.o gmac_ethtool.o gmac_phy.o gmac_desc.o gmac_offload.o
 +
-+    // Turn on first nine LEDs sequentially
-+    mdelay(1000);
-+    writel(LED_D1, GPIO_A_OUTPUT_CLEAR);
-+    mdelay(1000);
-+    writel(LED_D2, GPIO_A_OUTPUT_CLEAR);
-+    mdelay(1000);
-+    writel(LED_D3, GPIO_A_OUTPUT_CLEAR);
-+    mdelay(1000);
-+    writel(LED_D4, GPIO_A_OUTPUT_CLEAR);
-+    mdelay(1000);
-+    writel(LED_D5, GPIO_A_OUTPUT_CLEAR);
-+    mdelay(1000);
-+    writel(LED_D6, GPIO_A_OUTPUT_CLEAR);
-+    mdelay(1000);
-+    writel(LED_D7, GPIO_A_OUTPUT_CLEAR);
-+    mdelay(1000);
-+    writel(LED_D8, GPIO_A_OUTPUT_CLEAR);
-+    mdelay(1000);
-+    writel(LED_D9, GPIO_A_OUTPUT_CLEAR);
++obj-$(CONFIG_HIPOX_IBW) += ibw.o
 +
-+    // Turn on tenth LED
-+    mdelay(1000);
-+    writel(LED_D10, GPIO_B_OUTPUT_CLEAR);
++obj-$(CONFIG_TACHO_THERM_AND_FAN) += thermAndFan.o
 +
-+    // Disable primary, secondary and teriary GPIO functions for PWN line
-+    writel(readl(SYS_CTRL_GPIO_PRIMSEL_CTRL_0) & ~PWM_MASK, SYS_CTRL_GPIO_PRIMSEL_CTRL_0);
-+    writel(readl(SYS_CTRL_GPIO_SECSEL_CTRL_0)  & ~PWM_MASK, SYS_CTRL_GPIO_SECSEL_CTRL_0);
-+    writel(readl(SYS_CTRL_GPIO_TERTSEL_CTRL_0) & ~PWM_MASK, SYS_CTRL_GPIO_TERTSEL_CTRL_0);
++obj-$(CONFIG_I2S) += i2s.o
 +
-+    // Turn off PWM line
-+    writel(PWM_MASK, GPIO_A_OUTPUT_SET);
++obj-$(CONFIG_CRYPTO_OXAESLRW) += cipher.o
 +
-+    // Enable PWM line as output
-+    writel(PWM_MASK, GPIO_A_OUTPUT_ENABLE_SET);
++obj-$(CONFIG_GPIO_TEST)       += gpioTest.o
 +
-+    // Turn on PWM line
-+    mdelay(1000);
-+    writel(PWM_MASK, GPIO_A_OUTPUT_CLEAR);
-+}
-+#endif // CONFIG_HIPOX_LED_TEST
++obj-$(CONFIG_I2S) += i2s.o
 +
-+static void __init hipox_init_machine(void)
-+{
-+//printk("hipox_init_machine()\n");
-+    /* Initialise the spinlock used to make GPIO register set access atomic */
-+    spin_lock_init(&hipox_gpio_spinlock);
++obj-$(CONFIG_DPE_TEST) += dpe_test.o
 +
-+    /*
-+     * Initialise the support for our multi-channel memory-to-memory DMAC
-+     * The interrupt subsystem needs to be available before we can initialise
-+     * the DMAC support
-+     */
-+    hipox_dma_init();
++obj-$(CONFIG_HIPOX_AHB_MONITOR_MODULE) += hipox-ahb-monitor.o
 +
-+#ifdef CONFIG_DO_MEM_TEST
-+    /*
-+     * Do memory performance test
-+     */
-+    hipox_mem_test();
-+#endif // CONFIG_DO_MEM_TEST
++obj-$(CONFIG_HIPOX_USB_TEST_MODES) += usb-test-mode.o
 +
-+#ifdef CONFIG_LEON_START_EARLY
-+    init_copro(leon_early_srec, 0);
-+#endif // CONFIG_LEON_START_EARLY
++obj-$(CONFIG_LEON_POWER_BUTTON_MONITOR) += power_button.o
 +
-+#ifdef CONFIG_HIPOX_LED_TEST
-+    test_leds_and_pwm();
-+#endif // CONFIG_HIPOX_LED_TEST
++obj-$(CONFIG_USER_RECOVERY_BUTTON_MONITOR) += user_recovery_button.o
 +
-+      // Add any platform bus devices
-+      platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
-+}
++obj-$(CONFIG_HIPOX_FRONT_LAMP_CONTROL) += leds.o
 +
-+void sata_power_off(void)
-+{
-+#ifdef CONFIG_HIPOX_SATA_POWER_1
-+    // Disable power to SATA 1
-+    printk(KERN_INFO "Turning off disk 1\n");
-+    writel(SATA_POWER_1_MASK, SATA_POWER_1_OUTPUT_CLR_REG);
-+#endif // CONFIG_HIPOX_SATA_POWER_1
++obj-$(CONFIG_WDC_FAN_HIPOX800) += wdc-fan.o
 +
-+#ifdef CONFIG_HIPOX_SATA_POWER_2
-+    // Disable power to SATA 2
-+    printk(KERN_INFO "Turning off disk 2\n");
-+    writel(SATA_POWER_2_MASK, SATA_POWER_2_OUTPUT_CLR_REG);
-+#endif // CONFIG_HIPOX_SATA_POWER_2
-+}
++obj-$(CONFIG_WDC_LEDS_HIPOX800) += wdc-leds.o
 +
-+MACHINE_START(HIPOX, "OXE810 based HydraIP")
-+    /* Maintainer: Oxford Semiconductor Ltd */
-+#ifdef CONFIG_ARCH_HIPOX_UART1
-+    .phys_io = UART_1_BASE_PA,
-+    .io_pg_offst = (((u32)UART_1_BASE) >> 18) & 0xfffc,
-+#elif defined(CONFIG_ARCH_HIPOX_UART2)
-+    .phys_io = UART_2_BASE_PA,
-+    .io_pg_offst = (((u32)UART_2_BASE) >> 18) & 0xfffc,
-+#elif defined(CONFIG_ARCH_HIPOX_UART3)
-+    .phys_io = UART_3_BASE_PA,
-+    .io_pg_offst = (((u32)UART_3_BASE) >> 18) & 0xfffc,
-+#elif defined(CONFIG_ARCH_HIPOX_UART4)
-+    .phys_io = UART_4_BASE_PA,
-+    .io_pg_offst = (((u32)UART_4_BASE) >> 18) & 0xfffc,
-+#endif
-+    .boot_params = SDRAM_PA + 0x100,
-+    .fixup = hipox_fixup,
-+    .map_io = hipox_mapio,
-+    .init_irq = hipox_init_irq,
-+    .timer = &hipox_timer,
-+    .init_machine = hipox_init_machine,
-+MACHINE_END
++obj-$(CONFIG_HIPOX_WD810_LEDS) += hipox-wd810-leds.o
 +
-diff -Nurd linux-2.6.24/arch/arm/mach-hipox/pci.c linux-2.6.24-oxe810/arch/arm/mach-hipox/pci.c
---- linux-2.6.24/arch/arm/mach-hipox/pci.c     1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mach-hipox/pci.c      2008-06-11 17:47:55.000000000 +0200
++obj-$(CONFIG_WDC_LEDS_TRIGGER_SATA_DISK) += wdc-ledtrig-sata.o
+diff -Nurd linux-2.6.24.4/arch/arm/mach-hipox/Makefile.boot linux-2.6.24/arch/arm/mach-hipox/Makefile.boot
+--- linux-2.6.24.4/arch/arm/mach-hipox/Makefile.boot   1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/mach-hipox/Makefile.boot     2010-01-14 14:01:15.000000000 +0100
+@@ -0,0 +1,3 @@
++initrd_phys-$(CONFIG_ARCH_HIPOX)      := 0x48200000
++params_phys-$(CONFIG_ARCH_HIPOX)      := 0x48000100
++zreladdr-$(CONFIG_ARCH_HIPOX)         := 0x48008000
+diff -Nurd linux-2.6.24.4/arch/arm/mach-hipox/pci.c linux-2.6.24/arch/arm/mach-hipox/pci.c
+--- linux-2.6.24.4/arch/arm/mach-hipox/pci.c   1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/mach-hipox/pci.c     2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,678 @@
 +/*
 + *  arch/arm/mach-hipox/pci.c
@@ -24103,9 +23807,9 @@ diff -Nurd linux-2.6.24/arch/arm/mach-hipox/pci.c linux-2.6.24-oxe810/arch/arm/m
 +module_exit(hipox_pci_exit);
 +
 +#endif
-diff -Nurd linux-2.6.24/arch/arm/mach-hipox/power_button.c linux-2.6.24-oxe810/arch/arm/mach-hipox/power_button.c
---- linux-2.6.24/arch/arm/mach-hipox/power_button.c    1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mach-hipox/power_button.c     2008-06-11 17:47:55.000000000 +0200
+diff -Nurd linux-2.6.24.4/arch/arm/mach-hipox/power_button.c linux-2.6.24/arch/arm/mach-hipox/power_button.c
+--- linux-2.6.24.4/arch/arm/mach-hipox/power_button.c  1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/mach-hipox/power_button.c    2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,270 @@
 +/*
 + * linux/arch/arm/mach-hipox/power_button.c
@@ -24377,9 +24081,98 @@ diff -Nurd linux-2.6.24/arch/arm/mach-hipox/power_button.c linux-2.6.24-oxe810/a
 + */
 +module_init(power_button_init);
 +module_exit(power_button_exit);
-diff -Nurd linux-2.6.24/arch/arm/mach-hipox/samba_reserve.c linux-2.6.24-oxe810/arch/arm/mach-hipox/samba_reserve.c
---- linux-2.6.24/arch/arm/mach-hipox/samba_reserve.c   1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mach-hipox/samba_reserve.c    2008-06-11 17:47:55.000000000 +0200
+diff -Nurd linux-2.6.24.4/arch/arm/mach-hipox/README linux-2.6.24/arch/arm/mach-hipox/README
+--- linux-2.6.24.4/arch/arm/mach-hipox/README  1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/mach-hipox/README    2010-01-14 14:01:15.000000000 +0100
+@@ -0,0 +1,85 @@
++
++usb-test-modes 
++
++This is best built as a module which may be inserted into a running
++Linux system only when needed.
++The module can be built as part of the standard kernel module build
++if the correct options are chosen in the config. 
++
++
++How to use:
++
++copy the usb-test-mode.ko file somewhere convenient on the NAS and
++insert the module into the system using
++'modprobe usb-test-mode.ko'
++
++It should report successfull loading or an error message. Assuming it is
++successful /proc will have an 'usb_test_mode' entry (verify with ls).
++
++Actions:
++read the current port status:
++cat /proc/usb_test_mode/read
++
++set port 1 into test mode 4:
++echo 4 > /proc/usb_test_mode/write1
++
++
++When testing is completed the module can be removed from the linux
++system using:
++rmmod usb_test_mode
++
++ahb_mon 
++
++This should be built as a module. 
++
++How to use:
++
++insert the module into a working system by typing 
++'modprobe hipox-ahb-monitor'
++
++When successfully installed a directory  entry will appear in /proc for
++hipox-ahb-monitor. In the directory will be a writeable file for each
++AHB monitor and a control file. There will also be a readable file for
++obtaining the counts stored in all the ahb monitors.
++
++
++Actions:
++set a monitor to a limited range, burst mode etc using
++low addres, high address, mode, burst mode, burst mask, hprot, hprot mask
++
++Use the echo command to set data into the /proc/hipox-ahb-monitor an example is
++the following script to observe the activities of the ARM processor on the GMAC
++core when pinging a remote machine:
++---------------------------
++#!/bin/sh -x
++#
++
++# start montoring of ARM data bus to MAC
++# format is "low high mode burst mask hprot mask"
++# mode - 1 write 2 read 3 read write.
++
++echo 2 > /proc/hipox-test/control
++
++echo 0 > /proc/hipox-test/control
++
++
++echo "0x40400000,0x405fffff,3,0,0,0,0" > /proc/hipox-test/ARM_Data
++echo "0x40400000,0x405fffff,3,0,0,0,0" > /proc/hipox-test/Arm_Inst
++echo "0,4,3,0,0,0,0" > /proc/hipox-test/CoPro
++echo "0,4,3,0,0,0,0" > /proc/hipox-test/DMA_A
++echo "0,4,3,0,0,0,0" > /proc/hipox-test/DMA_B
++echo "0,4,3,0,0,0,0" > /proc/hipox-test/GMAC
++echo "0,4,3,0,0,0,0" > /proc/hipox-test/PCI
++echo "0,4,3,0,0,0,0" > /proc/hipox-test/USBHS
++
++echo 1 > /proc/hipox-test/control
++
++ping -c 1 172.31.0.102
++
++echo 0 > /proc/hipox-test/control
++--------------------------------------
++
++When testing is commplete the module can be removed using 
++rmmod hipox-ahb-monitor
++
++
+diff -Nurd linux-2.6.24.4/arch/arm/mach-hipox/samba_reserve.c linux-2.6.24/arch/arm/mach-hipox/samba_reserve.c
+--- linux-2.6.24.4/arch/arm/mach-hipox/samba_reserve.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/mach-hipox/samba_reserve.c   2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,50 @@
 +/*
 + * linux/arch/arm/mach-hipox/samba_receive.c
@@ -24431,9 +24224,9 @@ diff -Nurd linux-2.6.24/arch/arm/mach-hipox/samba_reserve.c linux-2.6.24-oxe810/
 +
 +      return ret;
 +}
-diff -Nurd linux-2.6.24/arch/arm/mach-hipox/thermAndFan.c linux-2.6.24-oxe810/arch/arm/mach-hipox/thermAndFan.c
---- linux-2.6.24/arch/arm/mach-hipox/thermAndFan.c     1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mach-hipox/thermAndFan.c      2008-06-11 17:47:55.000000000 +0200
+diff -Nurd linux-2.6.24.4/arch/arm/mach-hipox/thermAndFan.c linux-2.6.24/arch/arm/mach-hipox/thermAndFan.c
+--- linux-2.6.24.4/arch/arm/mach-hipox/thermAndFan.c   1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/mach-hipox/thermAndFan.c     2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,738 @@
 +/*
 + * Device driver for the i2c thermostat found on the iBook G4, Albook G4
@@ -25173,9 +24966,9 @@ diff -Nurd linux-2.6.24/arch/arm/mach-hipox/thermAndFan.c linux-2.6.24-oxe810/ar
 +
 +
 +/* End of File */
-diff -Nurd linux-2.6.24/arch/arm/mach-hipox/thermistorCalibration.h linux-2.6.24-oxe810/arch/arm/mach-hipox/thermistorCalibration.h
---- linux-2.6.24/arch/arm/mach-hipox/thermistorCalibration.h   1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mach-hipox/thermistorCalibration.h    2008-06-11 17:47:55.000000000 +0200
+diff -Nurd linux-2.6.24.4/arch/arm/mach-hipox/thermistorCalibration.h linux-2.6.24/arch/arm/mach-hipox/thermistorCalibration.h
+--- linux-2.6.24.4/arch/arm/mach-hipox/thermistorCalibration.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/mach-hipox/thermistorCalibration.h   2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,149 @@
 +#ifndef __THERMISTOR_LOOKUP_TABLE_10K3A_H
 +#define __THERMISTOR_LOOKUP_TABLE_10K3A_H
@@ -25326,9 +25119,9 @@ diff -Nurd linux-2.6.24/arch/arm/mach-hipox/thermistorCalibration.h linux-2.6.24
 +};
 +
 +#endif
-diff -Nurd linux-2.6.24/arch/arm/mach-hipox/time.c linux-2.6.24-oxe810/arch/arm/mach-hipox/time.c
---- linux-2.6.24/arch/arm/mach-hipox/time.c    1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mach-hipox/time.c     2008-06-11 17:47:55.000000000 +0200
+diff -Nurd linux-2.6.24.4/arch/arm/mach-hipox/time.c linux-2.6.24/arch/arm/mach-hipox/time.c
+--- linux-2.6.24.4/arch/arm/mach-hipox/time.c  1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/mach-hipox/time.c    2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,159 @@
 +/*
 + *  linux/arch/arm/mach-hipox/irq.c
@@ -25489,9 +25282,9 @@ diff -Nurd linux-2.6.24/arch/arm/mach-hipox/time.c linux-2.6.24-oxe810/arch/arm/
 +    .init   = hipox_init_time,
 +    .offset = hipox_gettimeoffset,
 +};
-diff -Nurd linux-2.6.24/arch/arm/mach-hipox/usb-test-mode.c linux-2.6.24-oxe810/arch/arm/mach-hipox/usb-test-mode.c
---- linux-2.6.24/arch/arm/mach-hipox/usb-test-mode.c   1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mach-hipox/usb-test-mode.c    2008-06-11 17:47:55.000000000 +0200
+diff -Nurd linux-2.6.24.4/arch/arm/mach-hipox/usb-test-mode.c linux-2.6.24/arch/arm/mach-hipox/usb-test-mode.c
+--- linux-2.6.24.4/arch/arm/mach-hipox/usb-test-mode.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/mach-hipox/usb-test-mode.c   2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,253 @@
 +/*
 + *  arch/arm/mach-hipox/usb-test-mode.c
@@ -25746,9 +25539,9 @@ diff -Nurd linux-2.6.24/arch/arm/mach-hipox/usb-test-mode.c linux-2.6.24-oxe810/
 +
 +
 +
-diff -Nurd linux-2.6.24/arch/arm/mach-hipox/user_recovery_button.c linux-2.6.24-oxe810/arch/arm/mach-hipox/user_recovery_button.c
---- linux-2.6.24/arch/arm/mach-hipox/user_recovery_button.c    1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mach-hipox/user_recovery_button.c     2008-06-11 17:47:55.000000000 +0200
+diff -Nurd linux-2.6.24.4/arch/arm/mach-hipox/user_recovery_button.c linux-2.6.24/arch/arm/mach-hipox/user_recovery_button.c
+--- linux-2.6.24.4/arch/arm/mach-hipox/user_recovery_button.c  1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/mach-hipox/user_recovery_button.c    2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,260 @@
 +/*
 + * linux/arch/arm/mach-hipox/user_recovery_button.c
@@ -26010,9 +25803,9 @@ diff -Nurd linux-2.6.24/arch/arm/mach-hipox/user_recovery_button.c linux-2.6.24-
 + */
 +module_init(recovery_button_init);
 +module_exit(recovery_button_exit);
-diff -Nurd linux-2.6.24/arch/arm/mach-hipox/wdc-fan.c linux-2.6.24-oxe810/arch/arm/mach-hipox/wdc-fan.c
---- linux-2.6.24/arch/arm/mach-hipox/wdc-fan.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mach-hipox/wdc-fan.c  2008-06-11 17:47:55.000000000 +0200
+diff -Nurd linux-2.6.24.4/arch/arm/mach-hipox/wdc-fan.c linux-2.6.24/arch/arm/mach-hipox/wdc-fan.c
+--- linux-2.6.24.4/arch/arm/mach-hipox/wdc-fan.c       1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/mach-hipox/wdc-fan.c 2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,336 @@
 +/*
 + * linux/arch/arm/mach-hipox/wdc-fan.c
@@ -26350,9 +26143,9 @@ diff -Nurd linux-2.6.24/arch/arm/mach-hipox/wdc-fan.c linux-2.6.24-oxe810/arch/a
 +MODULE_LICENSE("GPL");
 +
 +/*EOF*/
-diff -Nurd linux-2.6.24/arch/arm/mach-hipox/wdc-leds.c linux-2.6.24-oxe810/arch/arm/mach-hipox/wdc-leds.c
---- linux-2.6.24/arch/arm/mach-hipox/wdc-leds.c        1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mach-hipox/wdc-leds.c 2008-06-11 17:47:55.000000000 +0200
+diff -Nurd linux-2.6.24.4/arch/arm/mach-hipox/wdc-leds.c linux-2.6.24/arch/arm/mach-hipox/wdc-leds.c
+--- linux-2.6.24.4/arch/arm/mach-hipox/wdc-leds.c      1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/mach-hipox/wdc-leds.c        2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,1299 @@
 +/*
 + * linux/arch/arm/mach-hipox/wdc-leds.c
@@ -27653,9 +27446,9 @@ diff -Nurd linux-2.6.24/arch/arm/mach-hipox/wdc-leds.c linux-2.6.24-oxe810/arch/
 +MODULE_DESCRIPTION("WDC 2NC LEDs");
 +MODULE_LICENSE("GPL");
 +/******************************* End of File *********************************/
-diff -Nurd linux-2.6.24/arch/arm/mach-hipox/wdc-ledtrig-sata.c linux-2.6.24-oxe810/arch/arm/mach-hipox/wdc-ledtrig-sata.c
---- linux-2.6.24/arch/arm/mach-hipox/wdc-ledtrig-sata.c        1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mach-hipox/wdc-ledtrig-sata.c 2008-06-11 17:47:55.000000000 +0200
+diff -Nurd linux-2.6.24.4/arch/arm/mach-hipox/wdc-ledtrig-sata.c linux-2.6.24/arch/arm/mach-hipox/wdc-ledtrig-sata.c
+--- linux-2.6.24.4/arch/arm/mach-hipox/wdc-ledtrig-sata.c      1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/arch/arm/mach-hipox/wdc-ledtrig-sata.c        2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,78 @@
 +/*
 + * linux/arch/arm/mach-hipox/wdc-ledtrig-sata.c
@@ -27735,61 +27528,20 @@ diff -Nurd linux-2.6.24/arch/arm/mach-hipox/wdc-ledtrig-sata.c linux-2.6.24-oxe8
 +MODULE_LICENSE("GPL");
 +
 +/******************************* End of File *********************************/
-diff -Nurd linux-2.6.24/arch/arm/mach-pxa/clock.c linux-2.6.24-oxe810/arch/arm/mach-pxa/clock.c
---- linux-2.6.24/arch/arm/mach-pxa/clock.c     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mach-pxa/clock.c      2008-06-11 17:47:55.000000000 +0200
-@@ -23,18 +23,27 @@
- static DEFINE_MUTEX(clocks_mutex);
- static DEFINE_SPINLOCK(clocks_lock);
-+static struct clk *clk_lookup(struct device *dev, const char *id)
-+{
-+      struct clk *p;
-+
-+      list_for_each_entry(p, &clocks, node)
-+              if (strcmp(id, p->name) == 0 && p->dev == dev)
-+                      return p;
-+
-+      return NULL;
-+}
-+
- struct clk *clk_get(struct device *dev, const char *id)
- {
-       struct clk *p, *clk = ERR_PTR(-ENOENT);
-       mutex_lock(&clocks_mutex);
--      list_for_each_entry(p, &clocks, node) {
--              if (strcmp(id, p->name) == 0 &&
--                  (p->dev == NULL || p->dev == dev)) {
--                      clk = p;
--                      break;
--              }
--      }
-+      p = clk_lookup(dev, id);
-+      if (!p)
-+              p = clk_lookup(NULL, id);
-+      if (p)
-+              clk = p;
-       mutex_unlock(&clocks_mutex);
-       return clk;
-diff -Nurd linux-2.6.24/arch/arm/mm/Kconfig linux-2.6.24-oxe810/arch/arm/mm/Kconfig
---- linux-2.6.24/arch/arm/mm/Kconfig   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mm/Kconfig    2008-06-11 17:47:57.000000000 +0200
-@@ -171,8 +171,8 @@
- # ARM926T
- config CPU_ARM926T
-       bool "Support ARM926T processor"
--      depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_NS9XXX || ARCH_DAVINCI
--      default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_NS9XXX || ARCH_DAVINCI
-+      depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_NS9XXX || ARCH_DAVINCI || ARCH_HIPOX
-+      default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_NS9XXX || ARCH_DAVINCI || ARCH_HIPOX
-       select CPU_32v5
-       select CPU_ABRT_EV5TJ
-       select CPU_CACHE_VIVT
-diff -Nurd linux-2.6.24/arch/arm/mm/init.c linux-2.6.24-oxe810/arch/arm/mm/init.c
---- linux-2.6.24/arch/arm/mm/init.c    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mm/init.c     2008-06-11 17:47:57.000000000 +0200
+diff -Nurd linux-2.6.24.4/arch/arm/Makefile linux-2.6.24/arch/arm/Makefile
+--- linux-2.6.24.4/arch/arm/Makefile   2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/arch/arm/Makefile     2010-01-14 14:01:15.000000000 +0100
+@@ -127,6 +127,7 @@
+  machine-$(CONFIG_ARCH_VERSATILE)  := versatile
+  machine-$(CONFIG_ARCH_IMX)      := imx
+  machine-$(CONFIG_ARCH_H720X)    := h720x
++ machine-$(CONFIG_ARCH_HIPOX)    := hipox
+  machine-$(CONFIG_ARCH_AAEC2000)   := aaec2000
+  machine-$(CONFIG_ARCH_REALVIEW)   := realview
+  machine-$(CONFIG_ARCH_AT91)     := at91
+diff -Nurd linux-2.6.24.4/arch/arm/mm/init.c linux-2.6.24/arch/arm/mm/init.c
+--- linux-2.6.24.4/arch/arm/mm/init.c  2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/arch/arm/mm/init.c    2010-01-14 14:01:15.000000000 +0100
 @@ -173,9 +173,19 @@
  #ifdef CONFIG_MMU
        struct map_desc map;
@@ -27810,9 +27562,23 @@ diff -Nurd linux-2.6.24/arch/arm/mm/init.c linux-2.6.24-oxe810/arch/arm/mm/init.
        map.type = MT_MEMORY;
  
        create_mapping(&map);
-diff -Nurd linux-2.6.24/arch/arm/mm/mmu.c linux-2.6.24-oxe810/arch/arm/mm/mmu.c
---- linux-2.6.24/arch/arm/mm/mmu.c     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mm/mmu.c      2008-06-11 17:47:57.000000000 +0200
+diff -Nurd linux-2.6.24.4/arch/arm/mm/Kconfig linux-2.6.24/arch/arm/mm/Kconfig
+--- linux-2.6.24.4/arch/arm/mm/Kconfig 2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/arch/arm/mm/Kconfig   2010-01-14 14:01:15.000000000 +0100
+@@ -171,8 +171,8 @@
+ # ARM926T
+ config CPU_ARM926T
+       bool "Support ARM926T processor"
+-      depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_NS9XXX || ARCH_DAVINCI
+-      default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_NS9XXX || ARCH_DAVINCI
++      depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_NS9XXX || ARCH_DAVINCI || ARCH_HIPOX
++      default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 || ARCH_AT91SAM9263 || ARCH_AT91SAM9RL || ARCH_NS9XXX || ARCH_DAVINCI || ARCH_HIPOX
+       select CPU_32v5
+       select CPU_ABRT_EV5TJ
+       select CPU_CACHE_VIVT
+diff -Nurd linux-2.6.24.4/arch/arm/mm/mmu.c linux-2.6.24/arch/arm/mm/mmu.c
+--- linux-2.6.24.4/arch/arm/mm/mmu.c   2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/arch/arm/mm/mmu.c     2010-01-14 14:01:15.000000000 +0100
 @@ -617,6 +617,15 @@
        reserve_bootmem_node(pgdat, __pa(swapper_pg_dir),
                             PTRS_PER_PGD * sizeof(pgd_t));
@@ -27829,9 +27595,9 @@ diff -Nurd linux-2.6.24/arch/arm/mm/mmu.c linux-2.6.24-oxe810/arch/arm/mm/mmu.c
        /*
         * Hmm... This should go elsewhere, but we really really need to
         * stop things allocating the low memory; ideally we need a better
-diff -Nurd linux-2.6.24/arch/arm/mm/proc-arm926.S linux-2.6.24-oxe810/arch/arm/mm/proc-arm926.S
---- linux-2.6.24/arch/arm/mm/proc-arm926.S     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/arm/mm/proc-arm926.S      2008-06-11 17:47:57.000000000 +0200
+diff -Nurd linux-2.6.24.4/arch/arm/mm/proc-arm926.S linux-2.6.24/arch/arm/mm/proc-arm926.S
+--- linux-2.6.24.4/arch/arm/mm/proc-arm926.S   2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/arch/arm/mm/proc-arm926.S     2010-01-14 14:01:15.000000000 +0100
 @@ -245,6 +245,7 @@
   *
   * (same as v4wb)
@@ -27880,1073 +27646,9 @@ diff -Nurd linux-2.6.24/arch/arm/mm/proc-arm926.S linux-2.6.24-oxe810/arch/arm/m
  
  ENTRY(arm926_cache_fns)
        .long   arm926_flush_kern_cache_all
-diff -Nurd linux-2.6.24/arch/mips/kernel/i8259.c linux-2.6.24-oxe810/arch/mips/kernel/i8259.c
---- linux-2.6.24/arch/mips/kernel/i8259.c      2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/mips/kernel/i8259.c       2008-06-11 17:48:37.000000000 +0200
-@@ -338,8 +338,10 @@
-       init_8259A(0);
--      for (i = I8259A_IRQ_BASE; i < I8259A_IRQ_BASE + 16; i++)
-+      for (i = I8259A_IRQ_BASE; i < I8259A_IRQ_BASE + 16; i++) {
-               set_irq_chip_and_handler(i, &i8259A_chip, handle_level_irq);
-+              set_irq_probe(i);
-+      }
-       setup_irq(I8259A_IRQ_BASE + PIC_CASCADE_IR, &irq2);
- }
-diff -Nurd linux-2.6.24/arch/mips/kernel/irq.c linux-2.6.24-oxe810/arch/mips/kernel/irq.c
---- linux-2.6.24/arch/mips/kernel/irq.c        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/mips/kernel/irq.c 2008-06-11 17:48:37.000000000 +0200
-@@ -145,6 +145,11 @@
- void __init init_IRQ(void)
- {
-+      int i;
-+
-+      for (i = 0; i < NR_IRQS; i++)
-+              set_irq_noprobe(i);
-+
-       arch_init_irq();
- #ifdef CONFIG_KGDB
-diff -Nurd linux-2.6.24/arch/powerpc/platforms/chrp/pci.c linux-2.6.24-oxe810/arch/powerpc/platforms/chrp/pci.c
---- linux-2.6.24/arch/powerpc/platforms/chrp/pci.c     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/powerpc/platforms/chrp/pci.c      2008-06-11 17:47:35.000000000 +0200
-@@ -354,7 +354,7 @@
-  * mode as well. The same fixup must be done to the class-code property in
-  * the IDE node /pci@80000000/ide@C,1
-  */
--static void __devinit chrp_pci_fixup_vt8231_ata(struct pci_dev *viaide)
-+static void chrp_pci_fixup_vt8231_ata(struct pci_dev *viaide)
- {
-       u8 progif;
-       struct pci_dev *viaisa;
-@@ -375,4 +375,4 @@
-       pci_dev_put(viaisa);
- }
--DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, chrp_pci_fixup_vt8231_ata);
-+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, chrp_pci_fixup_vt8231_ata);
-diff -Nurd linux-2.6.24/arch/powerpc/platforms/powermac/feature.c linux-2.6.24-oxe810/arch/powerpc/platforms/powermac/feature.c
---- linux-2.6.24/arch/powerpc/platforms/powermac/feature.c     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/powerpc/platforms/powermac/feature.c      2008-06-11 17:47:38.000000000 +0200
-@@ -2565,6 +2565,8 @@
-       /* Locate core99 Uni-N */
-       uninorth_node = of_find_node_by_name(NULL, "uni-n");
-+      uninorth_maj = 1;
-+
-       /* Locate G5 u3 */
-       if (uninorth_node == NULL) {
-               uninorth_node = of_find_node_by_name(NULL, "u3");
-@@ -2575,8 +2577,10 @@
-               uninorth_node = of_find_node_by_name(NULL, "u4");
-               uninorth_maj = 4;
-       }
--      if (uninorth_node == NULL)
-+      if (uninorth_node == NULL) {
-+              uninorth_maj = 0;
-               return;
-+      }
-       addrp = of_get_property(uninorth_node, "reg", NULL);
-       if (addrp == NULL)
-@@ -3029,3 +3033,8 @@
-       pmac_agp_resume(pmac_agp_bridge);
- }
- EXPORT_SYMBOL(pmac_resume_agp_for_card);
-+
-+int pmac_get_uninorth_variant(void)
-+{
-+      return uninorth_maj;
-+}
-diff -Nurd linux-2.6.24/arch/s390/lib/uaccess_pt.c linux-2.6.24-oxe810/arch/s390/lib/uaccess_pt.c
---- linux-2.6.24/arch/s390/lib/uaccess_pt.c    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/s390/lib/uaccess_pt.c     2008-06-11 17:48:25.000000000 +0200
-@@ -406,6 +406,8 @@
- {
-       int ret;
-+      if (!current->mm)
-+              return -EFAULT;
-       spin_lock(&current->mm->page_table_lock);
-       uaddr = (int __user *) __dat_user_addr((unsigned long) uaddr);
-       if (!uaddr) {
-diff -Nurd linux-2.6.24/arch/s390/lib/uaccess_std.c linux-2.6.24-oxe810/arch/s390/lib/uaccess_std.c
---- linux-2.6.24/arch/s390/lib/uaccess_std.c   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/s390/lib/uaccess_std.c    2008-06-11 17:48:25.000000000 +0200
-@@ -293,10 +293,10 @@
-       asm volatile(
-               "   sacf 256\n"
--              "   cs   %1,%4,0(%5)\n"
--              "0: lr   %0,%1\n"
--              "1: sacf 0\n"
--              EX_TABLE(0b,1b)
-+              "0: cs   %1,%4,0(%5)\n"
-+              "1: lr   %0,%1\n"
-+              "2: sacf 0\n"
-+              EX_TABLE(0b,2b) EX_TABLE(1b,2b)
-               : "=d" (ret), "+d" (oldval), "=m" (*uaddr)
-               : "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr)
-               : "cc", "memory" );
-diff -Nurd linux-2.6.24/arch/sparc/kernel/Makefile linux-2.6.24-oxe810/arch/sparc/kernel/Makefile
---- linux-2.6.24/arch/sparc/kernel/Makefile    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/sparc/kernel/Makefile     2008-06-11 17:48:46.000000000 +0200
-@@ -1,4 +1,4 @@
--# $Id: Makefile,v 1.62 2000/12/15 00:41:17 davem Exp $
-+#
- # Makefile for the linux kernel.
- #
-@@ -12,7 +12,8 @@
-           sys_sparc.o sunos_asm.o systbls.o \
-           time.o windows.o cpu.o devices.o sclow.o \
-           tadpole.o tick14.o ptrace.o sys_solaris.o \
--          unaligned.o muldiv.o semaphore.o prom.o of_device.o devres.o
-+          unaligned.o una_asm.o muldiv.o semaphore.o \
-+          prom.o of_device.o devres.o
- devres-y = ../../../kernel/irq/devres.o
-diff -Nurd linux-2.6.24/arch/sparc/kernel/una_asm.S linux-2.6.24-oxe810/arch/sparc/kernel/una_asm.S
---- linux-2.6.24/arch/sparc/kernel/una_asm.S   1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/sparc/kernel/una_asm.S    2008-06-11 17:48:46.000000000 +0200
-@@ -0,0 +1,153 @@
-+/* una_asm.S: Kernel unaligned trap assembler helpers.
-+ *
-+ * Copyright (C) 1996,2005,2008 David S. Miller (davem@davemloft.net)
-+ * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
-+ */
-+
-+#include <linux/errno.h>
-+
-+      .text
-+
-+retl_efault:
-+      retl
-+       mov    -EFAULT, %o0
-+
-+      /* int __do_int_store(unsigned long *dst_addr, int size,
-+       *                    unsigned long *src_val)
-+       *
-+       * %o0 = dest_addr
-+       * %o1 = size
-+       * %o2 = src_val
-+       *
-+       * Return '0' on success, -EFAULT on failure.
-+       */
-+      .globl  __do_int_store
-+__do_int_store:
-+      ld      [%o2], %g1
-+      cmp     %1, 2
-+      be      2f
-+       cmp    %1, 4
-+      be      1f
-+       srl    %g1, 24, %g2
-+      srl     %g1, 16, %g7
-+4:    stb     %g2, [%o0]
-+      srl     %g1, 8, %g2
-+5:    stb     %g7, [%o0 + 1]
-+      ld      [%o2 + 4], %g7
-+6:    stb     %g2, [%o0 + 2]
-+      srl     %g7, 24, %g2
-+7:    stb     %g1, [%o0 + 3]
-+      srl     %g7, 16, %g1
-+8:    stb     %g2, [%o0 + 4]
-+      srl     %g7, 8, %g2
-+9:    stb     %g1, [%o0 + 5]
-+10:   stb     %g2, [%o0 + 6]
-+      b       0f
-+11:    stb    %g7, [%o0 + 7]
-+1:    srl     %g1, 16, %g7
-+12:   stb     %g2, [%o0]
-+      srl     %g1, 8, %g2
-+13:   stb     %g7, [%o0 + 1]
-+14:   stb     %g2, [%o0 + 2]
-+      b       0f
-+15:    stb    %g1, [%o0 + 3]
-+2:    srl     %g1, 8, %g2
-+16:   stb     %g2, [%o0]
-+17:   stb     %g1, [%o0 + 1]
-+0:    retl
-+       mov    0, %o0
-+
-+      .section __ex_table,#alloc
-+      .word   4b, retl_efault
-+      .word   5b, retl_efault
-+      .word   6b, retl_efault
-+      .word   7b, retl_efault
-+      .word   8b, retl_efault
-+      .word   9b, retl_efault
-+      .word   10b, retl_efault
-+      .word   11b, retl_efault
-+      .word   12b, retl_efault
-+      .word   13b, retl_efault
-+      .word   14b, retl_efault
-+      .word   15b, retl_efault
-+      .word   16b, retl_efault
-+      .word   17b, retl_efault
-+      .previous
-+
-+      /* int do_int_load(unsigned long *dest_reg, int size,
-+       *                 unsigned long *saddr, int is_signed)
-+       *
-+       * %o0 = dest_reg
-+       * %o1 = size
-+       * %o2 = saddr
-+       * %o3 = is_signed
-+       *
-+       * Return '0' on success, -EFAULT on failure.
-+       */
-+      .globl  do_int_load
-+do_int_load:
-+      cmp     %o1, 8
-+      be      9f
-+       cmp    %o1, 4
-+      be      6f
-+4:     ldub   [%o2], %g1
-+5:    ldub    [%o2 + 1], %g2
-+      sll     %g1, 8, %g1
-+      tst     %o3
-+      be      3f
-+       or     %g1, %g2, %g1
-+      sll     %g1, 16, %g1
-+      sra     %g1, 16, %g1
-+3:    b       0f
-+       st     %g1, [%o0]
-+6:    ldub    [%o2 + 1], %g2
-+      sll     %g1, 24, %g1
-+7:    ldub    [%o2 + 2], %g7
-+      sll     %g2, 16, %g2
-+8:    ldub    [%o2 + 3], %g3
-+      sll     %g7, 8, %g7
-+      or      %g3, %g2, %g3
-+      or      %g7, %g3, %g7
-+      or      %g1, %g7, %g1
-+      b       0f
-+       st     %g1, [%o0]
-+9:    ldub    [%o2], %g1
-+10:   ldub    [%o2 + 1], %g2
-+      sll     %g1, 24, %g1
-+11:   ldub    [%o2 + 2], %g7
-+      sll     %g2, 16, %g2
-+12:   ldub    [%o2 + 3], %g3
-+      sll     %g7, 8, %g7
-+      or      %g1, %g2, %g1
-+      or      %g7, %g3, %g7
-+      or      %g1, %g7, %g7
-+13:   ldub    [%o2 + 4], %g1
-+      st      %g7, [%o0]
-+14:   ldub    [%o2 + 5], %g2
-+      sll     %g1, 24, %g1
-+15:   ldub    [%o2 + 6], %g7
-+      sll     %g2, 16, %g2
-+16:   ldub    [%o2 + 7], %g3
-+      sll     %g7, 8, %g7
-+      or      %g1, %g2, %g1
-+      or      %g7, %g3, %g7
-+      or      %g1, %g7, %g7
-+      st      %g7, [%o0 + 4]
-+0:    retl
-+       mov    0, %o0
-+
-+      .section __ex_table,#alloc
-+      .word   4b, retl_efault
-+      .word   5b, retl_efault
-+      .word   6b, retl_efault
-+      .word   7b, retl_efault
-+      .word   8b, retl_efault
-+      .word   9b, retl_efault
-+      .word   10b, retl_efault
-+      .word   11b, retl_efault
-+      .word   12b, retl_efault
-+      .word   13b, retl_efault
-+      .word   14b, retl_efault
-+      .word   15b, retl_efault
-+      .word   16b, retl_efault
-+      .previous
-diff -Nurd linux-2.6.24/arch/sparc/kernel/unaligned.c linux-2.6.24-oxe810/arch/sparc/kernel/unaligned.c
---- linux-2.6.24/arch/sparc/kernel/unaligned.c 2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/sparc/kernel/unaligned.c  2008-06-11 17:48:46.000000000 +0200
-@@ -175,157 +175,31 @@
-       panic(str);
- }
--#define do_integer_load(dest_reg, size, saddr, is_signed, errh) ({            \
--__asm__ __volatile__ (                                                                \
--      "cmp    %1, 8\n\t"                                                      \
--      "be     9f\n\t"                                                         \
--      " cmp   %1, 4\n\t"                                                      \
--      "be     6f\n"                                                           \
--"4:\t"        " ldub  [%2], %%l1\n"                                                   \
--"5:\t"        "ldub   [%2 + 1], %%l2\n\t"                                             \
--      "sll    %%l1, 8, %%l1\n\t"                                              \
--      "tst    %3\n\t"                                                         \
--      "be     3f\n\t"                                                         \
--      " add   %%l1, %%l2, %%l1\n\t"                                           \
--      "sll    %%l1, 16, %%l1\n\t"                                             \
--      "sra    %%l1, 16, %%l1\n"                                               \
--"3:\t"        "b      0f\n\t"                                                         \
--      " st    %%l1, [%0]\n"                                                   \
--"6:\t"        "ldub   [%2 + 1], %%l2\n\t"                                             \
--      "sll    %%l1, 24, %%l1\n"                                               \
--"7:\t"        "ldub   [%2 + 2], %%g7\n\t"                                             \
--      "sll    %%l2, 16, %%l2\n"                                               \
--"8:\t"        "ldub   [%2 + 3], %%g1\n\t"                                             \
--      "sll    %%g7, 8, %%g7\n\t"                                              \
--      "or     %%l1, %%l2, %%l1\n\t"                                           \
--      "or     %%g7, %%g1, %%g7\n\t"                                           \
--      "or     %%l1, %%g7, %%l1\n\t"                                           \
--      "b      0f\n\t"                                                         \
--      " st    %%l1, [%0]\n"                                                   \
--"9:\t"        "ldub   [%2], %%l1\n"                                                   \
--"10:\t"       "ldub   [%2 + 1], %%l2\n\t"                                             \
--      "sll    %%l1, 24, %%l1\n"                                               \
--"11:\t"       "ldub   [%2 + 2], %%g7\n\t"                                             \
--      "sll    %%l2, 16, %%l2\n"                                               \
--"12:\t"       "ldub   [%2 + 3], %%g1\n\t"                                             \
--      "sll    %%g7, 8, %%g7\n\t"                                              \
--      "or     %%l1, %%l2, %%l1\n\t"                                           \
--      "or     %%g7, %%g1, %%g7\n\t"                                           \
--      "or     %%l1, %%g7, %%g7\n"                                             \
--"13:\t"       "ldub   [%2 + 4], %%l1\n\t"                                             \
--      "st     %%g7, [%0]\n"                                                   \
--"14:\t"       "ldub   [%2 + 5], %%l2\n\t"                                             \
--      "sll    %%l1, 24, %%l1\n"                                               \
--"15:\t"       "ldub   [%2 + 6], %%g7\n\t"                                             \
--      "sll    %%l2, 16, %%l2\n"                                               \
--"16:\t"       "ldub   [%2 + 7], %%g1\n\t"                                             \
--      "sll    %%g7, 8, %%g7\n\t"                                              \
--      "or     %%l1, %%l2, %%l1\n\t"                                           \
--      "or     %%g7, %%g1, %%g7\n\t"                                           \
--      "or     %%l1, %%g7, %%g7\n\t"                                           \
--      "st     %%g7, [%0 + 4]\n"                                               \
--"0:\n\n\t"                                                                    \
--      ".section __ex_table,#alloc\n\t"                                        \
--      ".word  4b, " #errh "\n\t"                                              \
--      ".word  5b, " #errh "\n\t"                                              \
--      ".word  6b, " #errh "\n\t"                                              \
--      ".word  7b, " #errh "\n\t"                                              \
--      ".word  8b, " #errh "\n\t"                                              \
--      ".word  9b, " #errh "\n\t"                                              \
--      ".word  10b, " #errh "\n\t"                                             \
--      ".word  11b, " #errh "\n\t"                                             \
--      ".word  12b, " #errh "\n\t"                                             \
--      ".word  13b, " #errh "\n\t"                                             \
--      ".word  14b, " #errh "\n\t"                                             \
--      ".word  15b, " #errh "\n\t"                                             \
--      ".word  16b, " #errh "\n\n\t"                                           \
--      ".previous\n\t"                                                         \
--      : : "r" (dest_reg), "r" (size), "r" (saddr), "r" (is_signed)            \
--      : "l1", "l2", "g7", "g1", "cc");                                        \
--})
--      
--#define store_common(dst_addr, size, src_val, errh) ({                                \
--__asm__ __volatile__ (                                                                \
--      "ld     [%2], %%l1\n"                                                   \
--      "cmp    %1, 2\n\t"                                                      \
--      "be     2f\n\t"                                                         \
--      " cmp   %1, 4\n\t"                                                      \
--      "be     1f\n\t"                                                         \
--      " srl   %%l1, 24, %%l2\n\t"                                             \
--      "srl    %%l1, 16, %%g7\n"                                               \
--"4:\t"        "stb    %%l2, [%0]\n\t"                                                 \
--      "srl    %%l1, 8, %%l2\n"                                                \
--"5:\t"        "stb    %%g7, [%0 + 1]\n\t"                                             \
--      "ld     [%2 + 4], %%g7\n"                                               \
--"6:\t"        "stb    %%l2, [%0 + 2]\n\t"                                             \
--      "srl    %%g7, 24, %%l2\n"                                               \
--"7:\t"        "stb    %%l1, [%0 + 3]\n\t"                                             \
--      "srl    %%g7, 16, %%l1\n"                                               \
--"8:\t"        "stb    %%l2, [%0 + 4]\n\t"                                             \
--      "srl    %%g7, 8, %%l2\n"                                                \
--"9:\t"        "stb    %%l1, [%0 + 5]\n"                                               \
--"10:\t"       "stb    %%l2, [%0 + 6]\n\t"                                             \
--      "b      0f\n"                                                           \
--"11:\t"       " stb   %%g7, [%0 + 7]\n"                                               \
--"1:\t"        "srl    %%l1, 16, %%g7\n"                                               \
--"12:\t"       "stb    %%l2, [%0]\n\t"                                                 \
--      "srl    %%l1, 8, %%l2\n"                                                \
--"13:\t"       "stb    %%g7, [%0 + 1]\n"                                               \
--"14:\t"       "stb    %%l2, [%0 + 2]\n\t"                                             \
--      "b      0f\n"                                                           \
--"15:\t"       " stb   %%l1, [%0 + 3]\n"                                               \
--"2:\t"        "srl    %%l1, 8, %%l2\n"                                                \
--"16:\t"       "stb    %%l2, [%0]\n"                                                   \
--"17:\t"       "stb    %%l1, [%0 + 1]\n"                                               \
--"0:\n\n\t"                                                                    \
--      ".section __ex_table,#alloc\n\t"                                        \
--      ".word  4b, " #errh "\n\t"                                              \
--      ".word  5b, " #errh "\n\t"                                              \
--      ".word  6b, " #errh "\n\t"                                              \
--      ".word  7b, " #errh "\n\t"                                              \
--      ".word  8b, " #errh "\n\t"                                              \
--      ".word  9b, " #errh "\n\t"                                              \
--      ".word  10b, " #errh "\n\t"                                             \
--      ".word  11b, " #errh "\n\t"                                             \
--      ".word  12b, " #errh "\n\t"                                             \
--      ".word  13b, " #errh "\n\t"                                             \
--      ".word  14b, " #errh "\n\t"                                             \
--      ".word  15b, " #errh "\n\t"                                             \
--      ".word  16b, " #errh "\n\t"                                             \
--      ".word  17b, " #errh "\n\n\t"                                           \
--      ".previous\n\t"                                                         \
--      : : "r" (dst_addr), "r" (size), "r" (src_val)                           \
--      : "l1", "l2", "g7", "g1", "cc");                                        \
--})
-+/* una_asm.S */
-+extern int do_int_load(unsigned long *dest_reg, int size,
-+                     unsigned long *saddr, int is_signed);
-+extern int __do_int_store(unsigned long *dst_addr, int size,
-+                        unsigned long *src_val);
--#define do_integer_store(reg_num, size, dst_addr, regs, errh) ({              \
--      unsigned long *src_val;                                                 \
--      static unsigned long zero[2] = { 0, };                                  \
--                                                                              \
--      if (reg_num) src_val = fetch_reg_addr(reg_num, regs);                   \
--      else {                                                                  \
--              src_val = &zero[0];                                             \
--              if (size == 8)                                                  \
--                      zero[1] = fetch_reg(1, regs);                           \
--      }                                                                       \
--      store_common(dst_addr, size, src_val, errh);                            \
--})
-+static int do_int_store(int reg_num, int size, unsigned long *dst_addr,
-+                      struct pt_regs *regs)
-+{
-+      unsigned long zero[2] = { 0, 0 };
-+      unsigned long *src_val;
-+
-+      if (reg_num)
-+              src_val = fetch_reg_addr(reg_num, regs);
-+      else {
-+              src_val = &zero[0];
-+              if (size == 8)
-+                      zero[1] = fetch_reg(1, regs);
-+      }
-+      return __do_int_store(dst_addr, size, src_val);
-+}
- extern void smp_capture(void);
- extern void smp_release(void);
--#define do_atomic(srcdest_reg, mem, errh) ({                                  \
--      unsigned long flags, tmp;                                               \
--                                                                              \
--      smp_capture();                                                          \
--      local_irq_save(flags);                                                  \
--      tmp = *srcdest_reg;                                                     \
--      do_integer_load(srcdest_reg, 4, mem, 0, errh);                          \
--      store_common(mem, 4, &tmp, errh);                                       \
--      local_irq_restore(flags);                                               \
--      smp_release();                                                          \
--})
--
- static inline void advance(struct pt_regs *regs)
- {
-       regs->pc   = regs->npc;
-@@ -342,9 +216,7 @@
-       return !floating_point_load_or_store_p(insn);
- }
--void kernel_mna_trap_fault(struct pt_regs *regs, unsigned int insn) __asm__ ("kernel_mna_trap_fault");
--
--void kernel_mna_trap_fault(struct pt_regs *regs, unsigned int insn)
-+static void kernel_mna_trap_fault(struct pt_regs *regs, unsigned int insn)
- {
-       unsigned long g2 = regs->u_regs [UREG_G2];
-       unsigned long fixup = search_extables_range(regs->pc, &g2);
-@@ -379,48 +251,34 @@
-               printk("Unsupported unaligned load/store trap for kernel at <%08lx>.\n",
-                      regs->pc);
-               unaligned_panic("Wheee. Kernel does fpu/atomic unaligned load/store.");
--
--              __asm__ __volatile__ ("\n"
--"kernel_unaligned_trap_fault:\n\t"
--              "mov    %0, %%o0\n\t"
--              "call   kernel_mna_trap_fault\n\t"
--              " mov   %1, %%o1\n\t"
--              :
--              : "r" (regs), "r" (insn)
--              : "o0", "o1", "o2", "o3", "o4", "o5", "o7",
--                "g1", "g2", "g3", "g4", "g5", "g7", "cc");
-       } else {
-               unsigned long addr = compute_effective_address(regs, insn);
-+              int err;
- #ifdef DEBUG_MNA
-               printk("KMNA: pc=%08lx [dir=%s addr=%08lx size=%d] retpc[%08lx]\n",
-                      regs->pc, dirstrings[dir], addr, size, regs->u_regs[UREG_RETPC]);
- #endif
--              switch(dir) {
-+              switch (dir) {
-               case load:
--                      do_integer_load(fetch_reg_addr(((insn>>25)&0x1f), regs),
--                                      size, (unsigned long *) addr,
--                                      decode_signedness(insn),
--                                      kernel_unaligned_trap_fault);
-+                      err = do_int_load(fetch_reg_addr(((insn>>25)&0x1f),
-+                                                       regs),
-+                                        size, (unsigned long *) addr,
-+                                        decode_signedness(insn));
-                       break;
-               case store:
--                      do_integer_store(((insn>>25)&0x1f), size,
--                                       (unsigned long *) addr, regs,
--                                       kernel_unaligned_trap_fault);
--                      break;
--#if 0 /* unsupported */
--              case both:
--                      do_atomic(fetch_reg_addr(((insn>>25)&0x1f), regs),
--                                (unsigned long *) addr,
--                                kernel_unaligned_trap_fault);
-+                      err = do_int_store(((insn>>25)&0x1f), size,
-+                                         (unsigned long *) addr, regs);
-                       break;
--#endif
-               default:
-                       panic("Impossible kernel unaligned trap.");
-                       /* Not reached... */
-               }
--              advance(regs);
-+              if (err)
-+                      kernel_mna_trap_fault(regs, insn);
-+              else
-+                      advance(regs);
-       }
- }
-@@ -459,9 +317,7 @@
-       return 0;
- }
--void user_mna_trap_fault(struct pt_regs *regs, unsigned int insn) __asm__ ("user_mna_trap_fault");
--
--void user_mna_trap_fault(struct pt_regs *regs, unsigned int insn)
-+static void user_mna_trap_fault(struct pt_regs *regs, unsigned int insn)
- {
-       siginfo_t info;
-@@ -485,7 +341,7 @@
-       if(!ok_for_user(regs, insn, dir)) {
-               goto kill_user;
-       } else {
--              int size = decode_access_size(insn);
-+              int err, size = decode_access_size(insn);
-               unsigned long addr;
-               if(floating_point_load_or_store_p(insn)) {
-@@ -496,48 +352,34 @@
-               addr = compute_effective_address(regs, insn);
-               switch(dir) {
-               case load:
--                      do_integer_load(fetch_reg_addr(((insn>>25)&0x1f), regs),
--                                      size, (unsigned long *) addr,
--                                      decode_signedness(insn),
--                                      user_unaligned_trap_fault);
-+                      err = do_int_load(fetch_reg_addr(((insn>>25)&0x1f),
-+                                                       regs),
-+                                        size, (unsigned long *) addr,
-+                                        decode_signedness(insn));
-                       break;
-               case store:
--                      do_integer_store(((insn>>25)&0x1f), size,
--                                       (unsigned long *) addr, regs,
--                                       user_unaligned_trap_fault);
-+                      err = do_int_store(((insn>>25)&0x1f), size,
-+                                         (unsigned long *) addr, regs);
-                       break;
-               case both:
--#if 0 /* unsupported */
--                      do_atomic(fetch_reg_addr(((insn>>25)&0x1f), regs),
--                                (unsigned long *) addr,
--                                user_unaligned_trap_fault);
--#else
-                       /*
-                        * This was supported in 2.4. However, we question
-                        * the value of SWAP instruction across word boundaries.
-                        */
-                       printk("Unaligned SWAP unsupported.\n");
--                      goto kill_user;
--#endif
-+                      err = -EFAULT;
-                       break;
-               default:
-                       unaligned_panic("Impossible user unaligned trap.");
--
--                      __asm__ __volatile__ ("\n"
--"user_unaligned_trap_fault:\n\t"
--                      "mov    %0, %%o0\n\t"
--                      "call   user_mna_trap_fault\n\t"
--                      " mov   %1, %%o1\n\t"
--                      :
--                      : "r" (regs), "r" (insn)
--                      : "o0", "o1", "o2", "o3", "o4", "o5", "o7",
--                        "g1", "g2", "g3", "g4", "g5", "g7", "cc");
-                       goto out;
-               }
--              advance(regs);
-+              if (err)
-+                      goto kill_user;
-+              else
-+                      advance(regs);
-               goto out;
-       }
-diff -Nurd linux-2.6.24/arch/sparc/lib/rwsem.S linux-2.6.24-oxe810/arch/sparc/lib/rwsem.S
---- linux-2.6.24/arch/sparc/lib/rwsem.S        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/sparc/lib/rwsem.S 2008-06-11 17:48:47.000000000 +0200
-@@ -7,7 +7,7 @@
- #include <asm/ptrace.h>
- #include <asm/psr.h>
--      .section .sched.text
-+      .section .sched.text, "ax"
-       .align  4
-       .globl          ___down_read
-diff -Nurd linux-2.6.24/arch/sparc64/lib/rwsem.S linux-2.6.24-oxe810/arch/sparc64/lib/rwsem.S
---- linux-2.6.24/arch/sparc64/lib/rwsem.S      2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/sparc64/lib/rwsem.S       2008-06-11 17:48:11.000000000 +0200
-@@ -6,7 +6,7 @@
- #include <asm/rwsem-const.h>
--      .section        .sched.text
-+      .section        .sched.text, "ax"
-       .globl          __down_read
- __down_read:
-diff -Nurd linux-2.6.24/arch/sparc64/mm/fault.c linux-2.6.24-oxe810/arch/sparc64/mm/fault.c
---- linux-2.6.24/arch/sparc64/mm/fault.c       2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/sparc64/mm/fault.c        2008-06-11 17:48:12.000000000 +0200
-@@ -244,16 +244,8 @@
-       if (regs->tstate & TSTATE_PRIV) {
-               const struct exception_table_entry *entry;
--              if (asi == ASI_P && (insn & 0xc0800000) == 0xc0800000) {
--                      if (insn & 0x2000)
--                              asi = (regs->tstate >> 24);
--                      else
--                              asi = (insn >> 5);
--              }
--      
--              /* Look in asi.h: All _S asis have LS bit set */
--              if ((asi & 0x1) &&
--                  (entry = search_exception_tables(regs->tpc))) {
-+              entry = search_exception_tables(regs->tpc);
-+              if (entry) {
-                       regs->tpc = entry->fixup;
-                       regs->tnpc = regs->tpc + 4;
-                       return;
-@@ -294,7 +286,7 @@
-               unsigned long tpc = regs->tpc;
-               /* Sanity check the PC. */
--              if ((tpc >= KERNBASE && tpc < (unsigned long) _etext) ||
-+              if ((tpc >= KERNBASE && tpc < (unsigned long) __init_end) ||
-                   (tpc >= MODULES_VADDR && tpc < MODULES_END)) {
-                       /* Valid, no problems... */
-               } else {
-diff -Nurd linux-2.6.24/arch/x86/ia32/ia32_signal.c linux-2.6.24-oxe810/arch/x86/ia32/ia32_signal.c
---- linux-2.6.24/arch/x86/ia32/ia32_signal.c   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/x86/ia32/ia32_signal.c    2008-06-11 17:48:21.000000000 +0200
-@@ -494,7 +494,7 @@
-       regs->ss = __USER32_DS; 
-       set_fs(USER_DS);
--      regs->eflags &= ~TF_MASK;
-+      regs->eflags &= ~(TF_MASK | X86_EFLAGS_DF);
-       if (test_thread_flag(TIF_SINGLESTEP))
-               ptrace_notify(SIGTRAP);
-@@ -600,7 +600,7 @@
-       regs->ss = __USER32_DS; 
-       set_fs(USER_DS);
--      regs->eflags &= ~TF_MASK;
-+      regs->eflags &= ~(TF_MASK | X86_EFLAGS_DF);
-       if (test_thread_flag(TIF_SINGLESTEP))
-               ptrace_notify(SIGTRAP);
-diff -Nurd linux-2.6.24/arch/x86/kernel/Makefile_32 linux-2.6.24-oxe810/arch/x86/kernel/Makefile_32
---- linux-2.6.24/arch/x86/kernel/Makefile_32   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/x86/kernel/Makefile_32    2008-06-11 17:48:20.000000000 +0200
-@@ -19,7 +19,8 @@
- obj-$(CONFIG_X86_CPUID)               += cpuid.o
- obj-$(CONFIG_MICROCODE)               += microcode.o
- obj-$(CONFIG_PCI)             += early-quirks.o
--obj-$(CONFIG_APM)             += apm_32.o
-+apm-y                         := apm_32.o
-+obj-$(CONFIG_APM)             += apm.o
- obj-$(CONFIG_X86_SMP)         += smp_32.o smpboot_32.o tsc_sync.o
- obj-$(CONFIG_SMP)             += smpcommon_32.o
- obj-$(CONFIG_X86_TRAMPOLINE)  += trampoline_32.o
-diff -Nurd linux-2.6.24/arch/x86/kernel/apic_32.c linux-2.6.24-oxe810/arch/x86/kernel/apic_32.c
---- linux-2.6.24/arch/x86/kernel/apic_32.c     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/x86/kernel/apic_32.c      2008-06-11 17:48:20.000000000 +0200
-@@ -154,7 +154,7 @@
- /**
-  * enable_NMI_through_LVT0 - enable NMI through local vector table 0
-  */
--void enable_NMI_through_LVT0 (void * dummy)
-+void __cpuinit enable_NMI_through_LVT0(void)
- {
-       unsigned int v = APIC_DM_NMI;
-diff -Nurd linux-2.6.24/arch/x86/kernel/apic_64.c linux-2.6.24-oxe810/arch/x86/kernel/apic_64.c
---- linux-2.6.24/arch/x86/kernel/apic_64.c     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/x86/kernel/apic_64.c      2008-06-11 17:48:20.000000000 +0200
-@@ -151,7 +151,7 @@
-       return send_status;
- }
--void enable_NMI_through_LVT0 (void * dummy)
-+void enable_NMI_through_LVT0(void)
- {
-       unsigned int v;
-diff -Nurd linux-2.6.24/arch/x86/kernel/io_apic_32.c linux-2.6.24-oxe810/arch/x86/kernel/io_apic_32.c
---- linux-2.6.24/arch/x86/kernel/io_apic_32.c  2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/x86/kernel/io_apic_32.c   2008-06-11 17:48:20.000000000 +0200
-@@ -2080,7 +2080,7 @@
-       .eoi            = ack_apic,
- };
--static void setup_nmi (void)
-+static void __init setup_nmi(void)
- {
-       /*
-        * Dirty trick to enable the NMI watchdog ...
-@@ -2093,7 +2093,7 @@
-        */ 
-       apic_printk(APIC_VERBOSE, KERN_INFO "activating NMI Watchdog ...");
--      on_each_cpu(enable_NMI_through_LVT0, NULL, 1, 1);
-+      enable_NMI_through_LVT0();
-       apic_printk(APIC_VERBOSE, " done.\n");
- }
-diff -Nurd linux-2.6.24/arch/x86/kernel/io_apic_64.c linux-2.6.24-oxe810/arch/x86/kernel/io_apic_64.c
---- linux-2.6.24/arch/x86/kernel/io_apic_64.c  2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/x86/kernel/io_apic_64.c   2008-06-11 17:48:20.000000000 +0200
-@@ -1565,7 +1565,7 @@
-       .end = end_lapic_irq,
- };
--static void setup_nmi (void)
-+static void __init setup_nmi(void)
- {
-       /*
-        * Dirty trick to enable the NMI watchdog ...
-@@ -1578,7 +1578,7 @@
-        */ 
-       printk(KERN_INFO "activating NMI Watchdog ...");
--      enable_NMI_through_LVT0(NULL);
-+      enable_NMI_through_LVT0();
-       printk(" done.\n");
- }
-@@ -1654,7 +1654,7 @@
-  *
-  * FIXME: really need to revamp this for modern platforms only.
-  */
--static inline void check_timer(void)
-+static inline void __init check_timer(void)
- {
-       struct irq_cfg *cfg = irq_cfg + 0;
-       int apic1, pin1, apic2, pin2;
-diff -Nurd linux-2.6.24/arch/x86/kernel/process_64.c linux-2.6.24-oxe810/arch/x86/kernel/process_64.c
---- linux-2.6.24/arch/x86/kernel/process_64.c  2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/x86/kernel/process_64.c   2008-06-11 17:48:20.000000000 +0200
-@@ -212,14 +212,13 @@
-       current_thread_info()->status |= TS_POLLING;
-       /* endless idle loop with no priority at all */
-       while (1) {
-+              tick_nohz_stop_sched_tick();
-               while (!need_resched()) {
-                       void (*idle)(void);
-                       if (__get_cpu_var(cpu_idle_state))
-                               __get_cpu_var(cpu_idle_state) = 0;
--                      tick_nohz_stop_sched_tick();
--
-                       rmb();
-                       idle = pm_idle;
-                       if (!idle)
-diff -Nurd linux-2.6.24/arch/x86/kernel/signal_32.c linux-2.6.24-oxe810/arch/x86/kernel/signal_32.c
---- linux-2.6.24/arch/x86/kernel/signal_32.c   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/x86/kernel/signal_32.c    2008-06-11 17:48:20.000000000 +0200
-@@ -396,7 +396,7 @@
-        * The tracer may want to single-step inside the
-        * handler too.
-        */
--      regs->eflags &= ~TF_MASK;
-+      regs->eflags &= ~(TF_MASK | X86_EFLAGS_DF);
-       if (test_thread_flag(TIF_SINGLESTEP))
-               ptrace_notify(SIGTRAP);
-@@ -489,7 +489,7 @@
-        * The tracer may want to single-step inside the
-        * handler too.
-        */
--      regs->eflags &= ~TF_MASK;
-+      regs->eflags &= ~(TF_MASK | X86_EFLAGS_DF);
-       if (test_thread_flag(TIF_SINGLESTEP))
-               ptrace_notify(SIGTRAP);
-diff -Nurd linux-2.6.24/arch/x86/kernel/signal_64.c linux-2.6.24-oxe810/arch/x86/kernel/signal_64.c
---- linux-2.6.24/arch/x86/kernel/signal_64.c   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/x86/kernel/signal_64.c    2008-06-11 17:48:20.000000000 +0200
-@@ -295,7 +295,7 @@
-          see include/asm-x86_64/uaccess.h for details. */
-       set_fs(USER_DS);
--      regs->eflags &= ~TF_MASK;
-+      regs->eflags &= ~(TF_MASK | X86_EFLAGS_DF);
-       if (test_thread_flag(TIF_SINGLESTEP))
-               ptrace_notify(SIGTRAP);
- #ifdef DEBUG_SIG
-diff -Nurd linux-2.6.24/arch/x86/kernel/smpboot_32.c linux-2.6.24-oxe810/arch/x86/kernel/smpboot_32.c
---- linux-2.6.24/arch/x86/kernel/smpboot_32.c  2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/x86/kernel/smpboot_32.c   2008-06-11 17:48:20.000000000 +0200
-@@ -405,7 +405,7 @@
-       setup_secondary_clock();
-       if (nmi_watchdog == NMI_IO_APIC) {
-               disable_8259A_irq(0);
--              enable_NMI_through_LVT0(NULL);
-+              enable_NMI_through_LVT0();
-               enable_8259A_irq(0);
-       }
-       /*
-diff -Nurd linux-2.6.24/arch/x86/kernel/smpboot_64.c linux-2.6.24-oxe810/arch/x86/kernel/smpboot_64.c
---- linux-2.6.24/arch/x86/kernel/smpboot_64.c  2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/x86/kernel/smpboot_64.c   2008-06-11 17:48:20.000000000 +0200
-@@ -338,7 +338,7 @@
-       if (nmi_watchdog == NMI_IO_APIC) {
-               disable_8259A_irq(0);
--              enable_NMI_through_LVT0(NULL);
-+              enable_NMI_through_LVT0();
-               enable_8259A_irq(0);
-       }
-diff -Nurd linux-2.6.24/arch/x86/mm/pageattr_64.c linux-2.6.24-oxe810/arch/x86/mm/pageattr_64.c
---- linux-2.6.24/arch/x86/mm/pageattr_64.c     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/x86/mm/pageattr_64.c      2008-06-11 17:48:22.000000000 +0200
-@@ -207,7 +207,7 @@
-               if (__pa(address) < KERNEL_TEXT_SIZE) {
-                       unsigned long addr2;
-                       pgprot_t prot2;
--                      addr2 = __START_KERNEL_map + __pa(address);
-+                      addr2 = __START_KERNEL_map + __pa(address) - phys_base;
-                       /* Make sure the kernel mappings stay executable */
-                       prot2 = pte_pgprot(pte_mkexec(pfn_pte(0, prot)));
-                       err = __change_page_attr(addr2, pfn, prot2,
-diff -Nurd linux-2.6.24/arch/x86/pci/mmconfig-shared.c linux-2.6.24-oxe810/arch/x86/pci/mmconfig-shared.c
---- linux-2.6.24/arch/x86/pci/mmconfig-shared.c        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/x86/pci/mmconfig-shared.c 2008-06-11 17:48:22.000000000 +0200
-@@ -22,42 +22,9 @@
- #define MMCONFIG_APER_MIN     (2 * 1024*1024)
- #define MMCONFIG_APER_MAX     (256 * 1024*1024)
--DECLARE_BITMAP(pci_mmcfg_fallback_slots, 32*PCI_MMCFG_MAX_CHECK_BUS);
--
- /* Indicate if the mmcfg resources have been placed into the resource table. */
- static int __initdata pci_mmcfg_resources_inserted;
--/* K8 systems have some devices (typically in the builtin northbridge)
--   that are only accessible using type1
--   Normally this can be expressed in the MCFG by not listing them
--   and assigning suitable _SEGs, but this isn't implemented in some BIOS.
--   Instead try to discover all devices on bus 0 that are unreachable using MM
--   and fallback for them. */
--static void __init unreachable_devices(void)
--{
--      int i, bus;
--      /* Use the max bus number from ACPI here? */
--      for (bus = 0; bus < PCI_MMCFG_MAX_CHECK_BUS; bus++) {
--              for (i = 0; i < 32; i++) {
--                      unsigned int devfn = PCI_DEVFN(i, 0);
--                      u32 val1, val2;
--
--                      pci_conf1_read(0, bus, devfn, 0, 4, &val1);
--                      if (val1 == 0xffffffff)
--                              continue;
--
--                      if (pci_mmcfg_arch_reachable(0, bus, devfn)) {
--                              raw_pci_ops->read(0, bus, devfn, 0, 4, &val2);
--                              if (val1 == val2)
--                                      continue;
--                      }
--                      set_bit(i + 32 * bus, pci_mmcfg_fallback_slots);
--                      printk(KERN_NOTICE "PCI: No mmconfig possible on device"
--                             " %02x:%02x\n", bus, i);
--              }
--      }
--}
--
- static const char __init *pci_mmcfg_e7520(void)
- {
-       u32 win;
-@@ -270,8 +237,6 @@
-               return;
-       if (pci_mmcfg_arch_init()) {
--              if (type == 1)
--                      unreachable_devices();
-               if (known_bridge)
-                       pci_mmcfg_insert_resources(IORESOURCE_BUSY);
-               pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
-diff -Nurd linux-2.6.24/arch/x86/pci/mmconfig_32.c linux-2.6.24-oxe810/arch/x86/pci/mmconfig_32.c
---- linux-2.6.24/arch/x86/pci/mmconfig_32.c    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/x86/pci/mmconfig_32.c     2008-06-11 17:48:22.000000000 +0200
-@@ -30,10 +30,6 @@
-       struct acpi_mcfg_allocation *cfg;
-       int cfg_num;
--      if (seg == 0 && bus < PCI_MMCFG_MAX_CHECK_BUS &&
--          test_bit(PCI_SLOT(devfn) + 32*bus, pci_mmcfg_fallback_slots))
--              return 0;
--
-       for (cfg_num = 0; cfg_num < pci_mmcfg_config_num; cfg_num++) {
-               cfg = &pci_mmcfg_config[cfg_num];
-               if (cfg->pci_segment == seg &&
-@@ -68,13 +64,16 @@
-       u32 base;
-       if ((bus > 255) || (devfn > 255) || (reg > 4095)) {
--              *value = -1;
-+err:          *value = -1;
-               return -EINVAL;
-       }
-+      if (reg < 256)
-+              return pci_conf1_read(seg,bus,devfn,reg,len,value);
-+
-       base = get_base_addr(seg, bus, devfn);
-       if (!base)
--              return pci_conf1_read(seg,bus,devfn,reg,len,value);
-+              goto err;
-       spin_lock_irqsave(&pci_config_lock, flags);
-@@ -105,9 +104,12 @@
-       if ((bus > 255) || (devfn > 255) || (reg > 4095))
-               return -EINVAL;
-+      if (reg < 256)
-+              return pci_conf1_write(seg,bus,devfn,reg,len,value);
-+
-       base = get_base_addr(seg, bus, devfn);
-       if (!base)
--              return pci_conf1_write(seg,bus,devfn,reg,len,value);
-+              return -EINVAL;
-       spin_lock_irqsave(&pci_config_lock, flags);
-@@ -134,12 +136,6 @@
-       .write =        pci_mmcfg_write,
- };
--int __init pci_mmcfg_arch_reachable(unsigned int seg, unsigned int bus,
--                                  unsigned int devfn)
--{
--      return get_base_addr(seg, bus, devfn) != 0;
--}
--
- int __init pci_mmcfg_arch_init(void)
- {
-       printk(KERN_INFO "PCI: Using MMCONFIG\n");
-diff -Nurd linux-2.6.24/arch/x86/pci/mmconfig_64.c linux-2.6.24-oxe810/arch/x86/pci/mmconfig_64.c
---- linux-2.6.24/arch/x86/pci/mmconfig_64.c    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/x86/pci/mmconfig_64.c     2008-06-11 17:48:22.000000000 +0200
-@@ -40,9 +40,7 @@
- static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn)
- {
-       char __iomem *addr;
--      if (seg == 0 && bus < PCI_MMCFG_MAX_CHECK_BUS &&
--              test_bit(32*bus + PCI_SLOT(devfn), pci_mmcfg_fallback_slots))
--              return NULL;
-+
-       addr = get_virt(seg, bus);
-       if (!addr)
-               return NULL;
-@@ -56,13 +54,16 @@
-       /* Why do we have this when nobody checks it. How about a BUG()!? -AK */
-       if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095))) {
--              *value = -1;
-+err:          *value = -1;
-               return -EINVAL;
-       }
-+      if (reg < 256)
-+              return pci_conf1_read(seg,bus,devfn,reg,len,value);
-+
-       addr = pci_dev_base(seg, bus, devfn);
-       if (!addr)
--              return pci_conf1_read(seg,bus,devfn,reg,len,value);
-+              goto err;
-       switch (len) {
-       case 1:
-@@ -88,9 +89,12 @@
-       if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095)))
-               return -EINVAL;
-+      if (reg < 256)
-+              return pci_conf1_write(seg,bus,devfn,reg,len,value);
-+
-       addr = pci_dev_base(seg, bus, devfn);
-       if (!addr)
--              return pci_conf1_write(seg,bus,devfn,reg,len,value);
-+              return -EINVAL;
-       switch (len) {
-       case 1:
-@@ -126,12 +130,6 @@
-       return addr;
- }
--int __init pci_mmcfg_arch_reachable(unsigned int seg, unsigned int bus,
--                                  unsigned int devfn)
--{
--      return pci_dev_base(seg, bus, devfn) != NULL;
--}
--
- int __init pci_mmcfg_arch_init(void)
- {
-       int i;
-diff -Nurd linux-2.6.24/arch/x86/pci/pci.h linux-2.6.24-oxe810/arch/x86/pci/pci.h
---- linux-2.6.24/arch/x86/pci/pci.h    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/arch/x86/pci/pci.h     2008-06-11 17:48:22.000000000 +0200
-@@ -98,13 +98,6 @@
- /* pci-mmconfig.c */
--/* Verify the first 16 busses. We assume that systems with more busses
--   get MCFG right. */
--#define PCI_MMCFG_MAX_CHECK_BUS 16
--extern DECLARE_BITMAP(pci_mmcfg_fallback_slots, 32*PCI_MMCFG_MAX_CHECK_BUS);
--
--extern int __init pci_mmcfg_arch_reachable(unsigned int seg, unsigned int bus,
--                                         unsigned int devfn);
- extern int __init pci_mmcfg_arch_init(void);
- /*
-diff -Nurd linux-2.6.24/block/ll_rw_blk.c linux-2.6.24-oxe810/block/ll_rw_blk.c
---- linux-2.6.24/block/ll_rw_blk.c     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/block/ll_rw_blk.c      2008-06-11 17:46:40.000000000 +0200
+diff -Nurd linux-2.6.24.4/block/ll_rw_blk.c linux-2.6.24/block/ll_rw_blk.c
+--- linux-2.6.24.4/block/ll_rw_blk.c   2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/block/ll_rw_blk.c     2010-01-14 14:01:15.000000000 +0100
 @@ -1424,6 +1424,13 @@
        else
                max_sectors = q->max_sectors;
@@ -29017,278 +27719,9 @@ diff -Nurd linux-2.6.24/block/ll_rw_blk.c linux-2.6.24-oxe810/block/ll_rw_blk.c
        switch (el_ret) {
                case ELEVATOR_BACK_MERGE:
                        BUG_ON(!rq_mergeable(req));
-diff -Nurd linux-2.6.24/crypto/async_tx/async_xor.c linux-2.6.24-oxe810/crypto/async_tx/async_xor.c
---- linux-2.6.24/crypto/async_tx/async_xor.c   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/crypto/async_tx/async_xor.c    2008-06-11 17:43:37.000000000 +0200
-@@ -264,7 +264,7 @@
-       BUG_ON(src_cnt <= 1);
--      if (tx) {
-+      if (tx && src_cnt <= device->max_xor) {
-               dma_addr_t dma_addr;
-               enum dma_data_direction dir;
-diff -Nurd linux-2.6.24/crypto/xcbc.c linux-2.6.24-oxe810/crypto/xcbc.c
---- linux-2.6.24/crypto/xcbc.c 2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/crypto/xcbc.c  2008-06-11 17:43:39.000000000 +0200
-@@ -124,6 +124,11 @@
-               unsigned int offset = sg[i].offset;
-               unsigned int slen = sg[i].length;
-+              if (unlikely(slen > nbytes))
-+                      slen = nbytes;
-+
-+              nbytes -= slen;
-+
-               while (slen > 0) {
-                       unsigned int len = min(slen, ((unsigned int)(PAGE_SIZE)) - offset);
-                       char *p = crypto_kmap(pg, 0) + offset;
-@@ -177,7 +182,6 @@
-                       offset = 0;
-                       pg++;
-               }
--              nbytes-=sg[i].length;
-               i++;
-       } while (nbytes>0);
-diff -Nurd linux-2.6.24/crypto/xts.c linux-2.6.24-oxe810/crypto/xts.c
---- linux-2.6.24/crypto/xts.c  2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/crypto/xts.c   2008-06-11 17:43:39.000000000 +0200
-@@ -77,16 +77,16 @@
- }
- struct sinfo {
--      be128 t;
-+      be128 *t;
-       struct crypto_tfm *tfm;
-       void (*fn)(struct crypto_tfm *, u8 *, const u8 *);
- };
- static inline void xts_round(struct sinfo *s, void *dst, const void *src)
- {
--      be128_xor(dst, &s->t, src);             /* PP <- T xor P */
-+      be128_xor(dst, s->t, src);              /* PP <- T xor P */
-       s->fn(s->tfm, dst, dst);                /* CC <- E(Key1,PP) */
--      be128_xor(dst, dst, &s->t);             /* C <- T xor CC */
-+      be128_xor(dst, dst, s->t);              /* C <- T xor CC */
- }
- static int crypt(struct blkcipher_desc *d,
-@@ -101,7 +101,6 @@
-               .tfm = crypto_cipher_tfm(ctx->child),
-               .fn = fn
-       };
--      be128 *iv;
-       u8 *wsrc;
-       u8 *wdst;
-@@ -109,20 +108,20 @@
-       if (!w->nbytes)
-               return err;
-+      s.t = (be128 *)w->iv;
-       avail = w->nbytes;
-       wsrc = w->src.virt.addr;
-       wdst = w->dst.virt.addr;
-       /* calculate first value of T */
--      iv = (be128 *)w->iv;
--      tw(crypto_cipher_tfm(ctx->tweak), (void *)&s.t, w->iv);
-+      tw(crypto_cipher_tfm(ctx->tweak), w->iv, w->iv);
-       goto first;
-       for (;;) {
-               do {
--                      gf128mul_x_ble(&s.t, &s.t);
-+                      gf128mul_x_ble(s.t, s.t);
- first:
-                       xts_round(&s, wdst, wsrc);
-diff -Nurd linux-2.6.24/drivers/acorn/char/defkeymap-l7200.c linux-2.6.24-oxe810/drivers/acorn/char/defkeymap-l7200.c
---- linux-2.6.24/drivers/acorn/char/defkeymap-l7200.c  2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/acorn/char/defkeymap-l7200.c   2008-06-11 17:49:37.000000000 +0200
-@@ -347,40 +347,40 @@
- };
- struct kbdiacruc accent_table[MAX_DIACR] = {
--      {'`', 'A', '\300'},     {'`', 'a', '\340'},
--      {'\'', 'A', '\301'},    {'\'', 'a', '\341'},
--      {'^', 'A', '\302'},     {'^', 'a', '\342'},
--      {'~', 'A', '\303'},     {'~', 'a', '\343'},
--      {'"', 'A', '\304'},     {'"', 'a', '\344'},
--      {'O', 'A', '\305'},     {'o', 'a', '\345'},
--      {'0', 'A', '\305'},     {'0', 'a', '\345'},
--      {'A', 'A', '\305'},     {'a', 'a', '\345'},
--      {'A', 'E', '\306'},     {'a', 'e', '\346'},
--      {',', 'C', '\307'},     {',', 'c', '\347'},
--      {'`', 'E', '\310'},     {'`', 'e', '\350'},
--      {'\'', 'E', '\311'},    {'\'', 'e', '\351'},
--      {'^', 'E', '\312'},     {'^', 'e', '\352'},
--      {'"', 'E', '\313'},     {'"', 'e', '\353'},
--      {'`', 'I', '\314'},     {'`', 'i', '\354'},
--      {'\'', 'I', '\315'},    {'\'', 'i', '\355'},
--      {'^', 'I', '\316'},     {'^', 'i', '\356'},
--      {'"', 'I', '\317'},     {'"', 'i', '\357'},
--      {'-', 'D', '\320'},     {'-', 'd', '\360'},
--      {'~', 'N', '\321'},     {'~', 'n', '\361'},
--      {'`', 'O', '\322'},     {'`', 'o', '\362'},
--      {'\'', 'O', '\323'},    {'\'', 'o', '\363'},
--      {'^', 'O', '\324'},     {'^', 'o', '\364'},
--      {'~', 'O', '\325'},     {'~', 'o', '\365'},
--      {'"', 'O', '\326'},     {'"', 'o', '\366'},
--      {'/', 'O', '\330'},     {'/', 'o', '\370'},
--      {'`', 'U', '\331'},     {'`', 'u', '\371'},
--      {'\'', 'U', '\332'},    {'\'', 'u', '\372'},
--      {'^', 'U', '\333'},     {'^', 'u', '\373'},
--      {'"', 'U', '\334'},     {'"', 'u', '\374'},
--      {'\'', 'Y', '\335'},    {'\'', 'y', '\375'},
--      {'T', 'H', '\336'},     {'t', 'h', '\376'},
--      {'s', 's', '\337'},     {'"', 'y', '\377'},
--      {'s', 'z', '\337'},     {'i', 'j', '\377'},
-+      {'`', 'A', 0300},       {'`', 'a', 0340},
-+      {'\'', 'A', 0301},      {'\'', 'a', 0341},
-+      {'^', 'A', 0302},       {'^', 'a', 0342},
-+      {'~', 'A', 0303},       {'~', 'a', 0343},
-+      {'"', 'A', 0304},       {'"', 'a', 0344},
-+      {'O', 'A', 0305},       {'o', 'a', 0345},
-+      {'0', 'A', 0305},       {'0', 'a', 0345},
-+      {'A', 'A', 0305},       {'a', 'a', 0345},
-+      {'A', 'E', 0306},       {'a', 'e', 0346},
-+      {',', 'C', 0307},       {',', 'c', 0347},
-+      {'`', 'E', 0310},       {'`', 'e', 0350},
-+      {'\'', 'E', 0311},      {'\'', 'e', 0351},
-+      {'^', 'E', 0312},       {'^', 'e', 0352},
-+      {'"', 'E', 0313},       {'"', 'e', 0353},
-+      {'`', 'I', 0314},       {'`', 'i', 0354},
-+      {'\'', 'I', 0315},      {'\'', 'i', 0355},
-+      {'^', 'I', 0316},       {'^', 'i', 0356},
-+      {'"', 'I', 0317},       {'"', 'i', 0357},
-+      {'-', 'D', 0320},       {'-', 'd', 0360},
-+      {'~', 'N', 0321},       {'~', 'n', 0361},
-+      {'`', 'O', 0322},       {'`', 'o', 0362},
-+      {'\'', 'O', 0323},      {'\'', 'o', 0363},
-+      {'^', 'O', 0324},       {'^', 'o', 0364},
-+      {'~', 'O', 0325},       {'~', 'o', 0365},
-+      {'"', 'O', 0326},       {'"', 'o', 0366},
-+      {'/', 'O', 0330},       {'/', 'o', 0370},
-+      {'`', 'U', 0331},       {'`', 'u', 0371},
-+      {'\'', 'U', 0332},      {'\'', 'u', 0372},
-+      {'^', 'U', 0333},       {'^', 'u', 0373},
-+      {'"', 'U', 0334},       {'"', 'u', 0374},
-+      {'\'', 'Y', 0335},      {'\'', 'y', 0375},
-+      {'T', 'H', 0336},       {'t', 'h', 0376},
-+      {'s', 's', 0337},       {'"', 'y', 0377},
-+      {'s', 'z', 0337},       {'i', 'j', 0377},
- };
- unsigned int accent_table_size = 68;
-diff -Nurd linux-2.6.24/drivers/acpi/blacklist.c linux-2.6.24-oxe810/drivers/acpi/blacklist.c
---- linux-2.6.24/drivers/acpi/blacklist.c      2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/acpi/blacklist.c       2008-06-11 17:49:40.000000000 +0200
-@@ -208,24 +208,24 @@
-        * Disable OSI(Linux) warnings on all "Acer, inc."
-        *
-        * _OSI(Linux) disables the latest Windows BIOS code:
-+       * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3100"),
-        * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5050"),
-+       * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5100"),
-        * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5580"),
-        * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 3010"),
-        * _OSI(Linux) effect unknown:
-        * DMI_MATCH(DMI_PRODUCT_NAME, "Ferrari 5000"),
-        */
--      {
--      .callback = dmi_disable_osi_linux,
--      .ident = "Acer, inc.",
--      .matches = {
--                   DMI_MATCH(DMI_SYS_VENDOR, "Acer, inc."),
--              },
--      },
-+      /*
-+       * note that dmi_check_system() uses strstr()
-+       * to match sub-strings rather than !strcmp(),
-+       * so "Acer" below matches "Acer, inc." above.
-+       */
-       /*
-        * Disable OSI(Linux) warnings on all "Acer"
-        *
-        * _OSI(Linux) effect unknown:
--       * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5100"),
-+       * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5315"),
-        * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5610"),
-        * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7720Z"),
-        * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 5520"),
-@@ -300,7 +300,7 @@
-                    DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"),
-               },
-       },
--      { /* OSI(Linux) touches USB, breaks suspend to disk */
-+      { /* OSI(Linux) touches USB, unknown side-effect */
-       .callback = dmi_disable_osi_linux,
-       .ident = "Dell Dimension 5150",
-       .matches = {
-@@ -474,6 +474,11 @@
-        *
-        * _OSI(Linux) confirmed to be a NOP:
-        * DMI_MATCH(DMI_PRODUCT_NAME, "P1-J150B"),
-+       * with DMI_MATCH(DMI_BOARD_NAME, "ROCKY"),
-+       *
-+       * unknown:
-+       * DMI_MATCH(DMI_PRODUCT_NAME, "S1-MDGDG"),
-+       * with DMI_MATCH(DMI_BOARD_NAME, "ROCKY"),
-        */
-       {
-       .callback = dmi_disable_osi_linux,
-diff -Nurd linux-2.6.24/drivers/acpi/osl.c linux-2.6.24-oxe810/drivers/acpi/osl.c
---- linux-2.6.24/drivers/acpi/osl.c    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/acpi/osl.c     2008-06-11 17:49:40.000000000 +0200
-@@ -120,7 +120,7 @@
-  */
- #define OSI_LINUX_ENABLE 0
--struct osi_linux {
-+static struct osi_linux {
-       unsigned int    enable:1;
-       unsigned int    dmi:1;
-       unsigned int    cmdline:1;
-@@ -1213,24 +1213,24 @@
-  *
-  *    Returns 0 on success
-  */
--int acpi_dmi_dump(void)
-+static int acpi_dmi_dump(void)
- {
-       if (!dmi_available)
-               return -1;
-       printk(KERN_NOTICE PREFIX "DMI System Vendor: %s\n",
--              dmi_get_slot(DMI_SYS_VENDOR));
-+              dmi_get_system_info(DMI_SYS_VENDOR));
-       printk(KERN_NOTICE PREFIX "DMI Product Name: %s\n",
--              dmi_get_slot(DMI_PRODUCT_NAME));
-+              dmi_get_system_info(DMI_PRODUCT_NAME));
-       printk(KERN_NOTICE PREFIX "DMI Product Version: %s\n",
--              dmi_get_slot(DMI_PRODUCT_VERSION));
-+              dmi_get_system_info(DMI_PRODUCT_VERSION));
-       printk(KERN_NOTICE PREFIX "DMI Board Name: %s\n",
--              dmi_get_slot(DMI_BOARD_NAME));
-+              dmi_get_system_info(DMI_BOARD_NAME));
-       printk(KERN_NOTICE PREFIX "DMI BIOS Vendor: %s\n",
--              dmi_get_slot(DMI_BIOS_VENDOR));
-+              dmi_get_system_info(DMI_BIOS_VENDOR));
-       printk(KERN_NOTICE PREFIX "DMI BIOS Date: %s\n",
--              dmi_get_slot(DMI_BIOS_DATE));
-+              dmi_get_system_info(DMI_BIOS_DATE));
-       return 0;
- }
-diff -Nurd linux-2.6.24/drivers/ata/Kconfig linux-2.6.24-oxe810/drivers/ata/Kconfig
---- linux-2.6.24/drivers/ata/Kconfig   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/ata/Kconfig    2008-06-11 17:50:32.000000000 +0200
+diff -Nurd linux-2.6.24.4/drivers/ata/Kconfig linux-2.6.24/drivers/ata/Kconfig
+--- linux-2.6.24.4/drivers/ata/Kconfig 2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/drivers/ata/Kconfig   2010-01-14 14:01:15.000000000 +0100
 @@ -182,15 +182,49 @@
          firmware in the BIOS. This driver can sometimes handle
          otherwise unsupported hardware.
@@ -29340,21 +27773,9 @@ diff -Nurd linux-2.6.24/drivers/ata/Kconfig linux-2.6.24-oxe810/drivers/ata/Kcon
  config PATA_ALI
        tristate "ALi PATA support (Experimental)"
        depends on PCI && EXPERIMENTAL
-diff -Nurd linux-2.6.24/drivers/ata/Makefile linux-2.6.24-oxe810/drivers/ata/Makefile
---- linux-2.6.24/drivers/ata/Makefile  2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/ata/Makefile   2008-06-11 17:50:32.000000000 +0200
-@@ -18,6 +18,8 @@
- obj-$(CONFIG_SATA_INIC162X)   += sata_inic162x.o
- obj-$(CONFIG_PDC_ADMA)                += pdc_adma.o
- obj-$(CONFIG_SATA_FSL)                += sata_fsl.o
-+obj-$(CONFIG_SATA_OX800)      += ox800sata.o
-+obj-$(CONFIG_SATA_OX810)      += ox810sata.o
- obj-$(CONFIG_PATA_ALI)                += pata_ali.o
- obj-$(CONFIG_PATA_AMD)                += pata_amd.o
-diff -Nurd linux-2.6.24/drivers/ata/libata-core.c linux-2.6.24-oxe810/drivers/ata/libata-core.c
---- linux-2.6.24/drivers/ata/libata-core.c     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/ata/libata-core.c      2008-06-11 17:50:32.000000000 +0200
+diff -Nurd linux-2.6.24.4/drivers/ata/libata-core.c linux-2.6.24/drivers/ata/libata-core.c
+--- linux-2.6.24.4/drivers/ata/libata-core.c   2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/drivers/ata/libata-core.c     2010-01-14 14:01:15.000000000 +0100
 @@ -140,6 +140,8 @@
   */
  void ata_tf_to_fis(const struct ata_taskfile *tf, u8 pmp, int is_cmd, u8 *fis)
@@ -30795,9 +29216,9 @@ diff -Nurd linux-2.6.24/drivers/ata/libata-core.c linux-2.6.24-oxe810/drivers/at
        return AC_ERR_SYSTEM;
  }
  
-diff -Nurd linux-2.6.24/drivers/ata/libata-eh.c linux-2.6.24-oxe810/drivers/ata/libata-eh.c
---- linux-2.6.24/drivers/ata/libata-eh.c       2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/ata/libata-eh.c        2008-06-11 17:50:32.000000000 +0200
+diff -Nurd linux-2.6.24.4/drivers/ata/libata-eh.c linux-2.6.24/drivers/ata/libata-eh.c
+--- linux-2.6.24.4/drivers/ata/libata-eh.c     2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/drivers/ata/libata-eh.c       2010-01-14 14:01:15.000000000 +0100
 @@ -89,6 +89,8 @@
  static void __ata_ehi_pushv_desc(struct ata_eh_info *ehi, const char *fmt,
                                 va_list args)
@@ -31287,9 +29708,9 @@ diff -Nurd linux-2.6.24/drivers/ata/libata-eh.c linux-2.6.24-oxe810/drivers/ata/
        /* are we resuming? */
        spin_lock_irqsave(ap->lock, flags);
        if (!(ap->pflags & ATA_PFLAG_PM_PENDING) ||
-diff -Nurd linux-2.6.24/drivers/ata/libata-scsi.c linux-2.6.24-oxe810/drivers/ata/libata-scsi.c
---- linux-2.6.24/drivers/ata/libata-scsi.c     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/ata/libata-scsi.c      2008-06-11 17:50:32.000000000 +0200
+diff -Nurd linux-2.6.24.4/drivers/ata/libata-scsi.c linux-2.6.24/drivers/ata/libata-scsi.c
+--- linux-2.6.24.4/drivers/ata/libata-scsi.c   2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/drivers/ata/libata-scsi.c     2010-01-14 14:01:15.000000000 +0100
 @@ -1477,7 +1477,10 @@
  
        qc->scsidone(cmd);
@@ -31385,9 +29806,21 @@ diff -Nurd linux-2.6.24/drivers/ata/libata-scsi.c linux-2.6.24-oxe810/drivers/at
        /*
         * 12 and 16 byte CDBs use different offsets to
         * provide the various register values.
-diff -Nurd linux-2.6.24/drivers/ata/ox800sata.c linux-2.6.24-oxe810/drivers/ata/ox800sata.c
---- linux-2.6.24/drivers/ata/ox800sata.c       1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/ata/ox800sata.c        2008-06-11 17:50:32.000000000 +0200
+diff -Nurd linux-2.6.24.4/drivers/ata/Makefile linux-2.6.24/drivers/ata/Makefile
+--- linux-2.6.24.4/drivers/ata/Makefile        2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/drivers/ata/Makefile  2010-01-14 14:01:15.000000000 +0100
+@@ -18,6 +18,8 @@
+ obj-$(CONFIG_SATA_INIC162X)   += sata_inic162x.o
+ obj-$(CONFIG_PDC_ADMA)                += pdc_adma.o
+ obj-$(CONFIG_SATA_FSL)                += sata_fsl.o
++obj-$(CONFIG_SATA_OX800)      += ox800sata.o
++obj-$(CONFIG_SATA_OX810)      += ox810sata.o
+ obj-$(CONFIG_PATA_ALI)                += pata_ali.o
+ obj-$(CONFIG_PATA_AMD)                += pata_amd.o
+diff -Nurd linux-2.6.24.4/drivers/ata/ox800sata.c linux-2.6.24/drivers/ata/ox800sata.c
+--- linux-2.6.24.4/drivers/ata/ox800sata.c     1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/drivers/ata/ox800sata.c       2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,2184 @@
 +/**************************************************************************
 + *
@@ -33573,9 +32006,9 @@ diff -Nurd linux-2.6.24/drivers/ata/ox800sata.c linux-2.6.24-oxe810/drivers/ata/
 +EXPORT_SYMBOL( hipoxsata_RAID_faults );
 +EXPORT_SYMBOL( hipoxsata_get_port_no );
 +EXPORT_SYMBOL( hipoxsata_LBA_schemes_compatible );
-diff -Nurd linux-2.6.24/drivers/ata/ox810sata.c linux-2.6.24-oxe810/drivers/ata/ox810sata.c
---- linux-2.6.24/drivers/ata/ox810sata.c       1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/ata/ox810sata.c        2008-06-11 17:50:32.000000000 +0200
+diff -Nurd linux-2.6.24.4/drivers/ata/ox810sata.c linux-2.6.24/drivers/ata/ox810sata.c
+--- linux-2.6.24.4/drivers/ata/ox810sata.c     1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/drivers/ata/ox810sata.c       2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,2423 @@
 +/**************************************************************************
 + *
@@ -36000,304 +34433,9 @@ diff -Nurd linux-2.6.24/drivers/ata/ox810sata.c linux-2.6.24-oxe810/drivers/ata/
 + */
 +module_init(ox810sata_device_init);
 +module_exit(ox810sata_device_exit);
-diff -Nurd linux-2.6.24/drivers/ata/pata_hpt366.c linux-2.6.24-oxe810/drivers/ata/pata_hpt366.c
---- linux-2.6.24/drivers/ata/pata_hpt366.c     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/ata/pata_hpt366.c      2008-06-11 17:50:32.000000000 +0200
-@@ -27,7 +27,7 @@
- #include <linux/libata.h>
- #define DRV_NAME      "pata_hpt366"
--#define DRV_VERSION   "0.6.1"
-+#define DRV_VERSION   "0.6.2"
- struct hpt_clock {
-       u8      xfer_speed;
-@@ -180,9 +180,9 @@
-               if (hpt_dma_blacklisted(adev, "UDMA",  bad_ata33))
-                       mask &= ~ATA_MASK_UDMA;
-               if (hpt_dma_blacklisted(adev, "UDMA3", bad_ata66_3))
--                      mask &= ~(0x07 << ATA_SHIFT_UDMA);
-+                      mask &= ~(0xF8 << ATA_SHIFT_UDMA);
-               if (hpt_dma_blacklisted(adev, "UDMA4", bad_ata66_4))
--                      mask &= ~(0x0F << ATA_SHIFT_UDMA);
-+                      mask &= ~(0xF0 << ATA_SHIFT_UDMA);
-       }
-       return ata_pci_default_filter(adev, mask);
- }
-diff -Nurd linux-2.6.24/drivers/ata/pata_hpt37x.c linux-2.6.24-oxe810/drivers/ata/pata_hpt37x.c
---- linux-2.6.24/drivers/ata/pata_hpt37x.c     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/ata/pata_hpt37x.c      2008-06-11 17:50:32.000000000 +0200
-@@ -24,7 +24,7 @@
- #include <linux/libata.h>
- #define DRV_NAME      "pata_hpt37x"
--#define DRV_VERSION   "0.6.9"
-+#define DRV_VERSION   "0.6.11"
- struct hpt_clock {
-       u8      xfer_speed;
-@@ -281,7 +281,7 @@
-               if (hpt_dma_blacklisted(adev, "UDMA", bad_ata33))
-                       mask &= ~ATA_MASK_UDMA;
-               if (hpt_dma_blacklisted(adev, "UDMA100", bad_ata100_5))
--                      mask &= ~(0x1F << ATA_SHIFT_UDMA);
-+                      mask &= ~(0xE0 << ATA_SHIFT_UDMA);
-       }
-       return ata_pci_default_filter(adev, mask);
- }
-@@ -297,7 +297,7 @@
- {
-       if (adev->class == ATA_DEV_ATA) {
-               if (hpt_dma_blacklisted(adev, "UDMA100", bad_ata100_5))
--                      mask &= ~ (0x1F << ATA_SHIFT_UDMA);
-+                      mask &= ~(0xE0 << ATA_SHIFT_UDMA);
-       }
-       return ata_pci_default_filter(adev, mask);
- }
-diff -Nurd linux-2.6.24/drivers/ata/pata_serverworks.c linux-2.6.24-oxe810/drivers/ata/pata_serverworks.c
---- linux-2.6.24/drivers/ata/pata_serverworks.c        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/ata/pata_serverworks.c 2008-06-11 17:50:32.000000000 +0200
-@@ -226,7 +226,7 @@
-       for (i = 0; (p = csb_bad_ata100[i]) != NULL; i++) {
-               if (!strcmp(p, model_num))
--                      mask &= ~(0x1F << ATA_SHIFT_UDMA);
-+                      mask &= ~(0xE0 << ATA_SHIFT_UDMA);
-       }
-       return ata_pci_default_filter(adev, mask);
- }
-diff -Nurd linux-2.6.24/drivers/base/firmware_class.c linux-2.6.24-oxe810/drivers/base/firmware_class.c
---- linux-2.6.24/drivers/base/firmware_class.c 2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/base/firmware_class.c  2008-06-11 17:50:32.000000000 +0200
-@@ -292,7 +292,8 @@
- static inline void fw_setup_device_id(struct device *f_dev, struct device *dev)
- {
--      snprintf(f_dev->bus_id, BUS_ID_SIZE, "firmware-%s", dev->bus_id);
-+      /* XXX warning we should watch out for name collisions */
-+      strlcpy(f_dev->bus_id, dev->bus_id, BUS_ID_SIZE);
- }
- static int fw_register_device(struct device **dev_p, const char *fw_name,
-diff -Nurd linux-2.6.24/drivers/base/platform.c linux-2.6.24-oxe810/drivers/base/platform.c
---- linux-2.6.24/drivers/base/platform.c       2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/base/platform.c        2008-06-11 17:50:32.000000000 +0200
-@@ -647,7 +647,7 @@
-               high_totalram += high_totalram - 1;
-               mask = (((u64)high_totalram) << 32) + 0xffffffff;
-       }
--      return mask & *dev->dma_mask;
-+      return mask;
- }
- EXPORT_SYMBOL_GPL(dma_get_required_mask);
- #endif
-diff -Nurd linux-2.6.24/drivers/block/ub.c linux-2.6.24-oxe810/drivers/block/ub.c
---- linux-2.6.24/drivers/block/ub.c    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/block/ub.c     2008-06-11 17:49:32.000000000 +0200
-@@ -657,7 +657,6 @@
-       if ((cmd = ub_get_cmd(lun)) == NULL)
-               return -1;
-       memset(cmd, 0, sizeof(struct ub_scsi_cmd));
--      sg_init_table(cmd->sgv, UB_MAX_REQ_SG);
-       blkdev_dequeue_request(rq);
-@@ -668,6 +667,7 @@
-       /*
-        * get scatterlist from block layer
-        */
-+      sg_init_table(&urq->sgv[0], UB_MAX_REQ_SG);
-       n_elem = blk_rq_map_sg(lun->disk->queue, rq, &urq->sgv[0]);
-       if (n_elem < 0) {
-               /* Impossible, because blk_rq_map_sg should not hit ENOMEM. */
-diff -Nurd linux-2.6.24/drivers/char/defkeymap.c_shipped linux-2.6.24-oxe810/drivers/char/defkeymap.c_shipped
---- linux-2.6.24/drivers/char/defkeymap.c_shipped      2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/char/defkeymap.c_shipped       2008-06-11 17:49:52.000000000 +0200
-@@ -223,40 +223,40 @@
- };
- struct kbdiacruc accent_table[MAX_DIACR] = {
--      {'`', 'A', '\300'},     {'`', 'a', '\340'},
--      {'\'', 'A', '\301'},    {'\'', 'a', '\341'},
--      {'^', 'A', '\302'},     {'^', 'a', '\342'},
--      {'~', 'A', '\303'},     {'~', 'a', '\343'},
--      {'"', 'A', '\304'},     {'"', 'a', '\344'},
--      {'O', 'A', '\305'},     {'o', 'a', '\345'},
--      {'0', 'A', '\305'},     {'0', 'a', '\345'},
--      {'A', 'A', '\305'},     {'a', 'a', '\345'},
--      {'A', 'E', '\306'},     {'a', 'e', '\346'},
--      {',', 'C', '\307'},     {',', 'c', '\347'},
--      {'`', 'E', '\310'},     {'`', 'e', '\350'},
--      {'\'', 'E', '\311'},    {'\'', 'e', '\351'},
--      {'^', 'E', '\312'},     {'^', 'e', '\352'},
--      {'"', 'E', '\313'},     {'"', 'e', '\353'},
--      {'`', 'I', '\314'},     {'`', 'i', '\354'},
--      {'\'', 'I', '\315'},    {'\'', 'i', '\355'},
--      {'^', 'I', '\316'},     {'^', 'i', '\356'},
--      {'"', 'I', '\317'},     {'"', 'i', '\357'},
--      {'-', 'D', '\320'},     {'-', 'd', '\360'},
--      {'~', 'N', '\321'},     {'~', 'n', '\361'},
--      {'`', 'O', '\322'},     {'`', 'o', '\362'},
--      {'\'', 'O', '\323'},    {'\'', 'o', '\363'},
--      {'^', 'O', '\324'},     {'^', 'o', '\364'},
--      {'~', 'O', '\325'},     {'~', 'o', '\365'},
--      {'"', 'O', '\326'},     {'"', 'o', '\366'},
--      {'/', 'O', '\330'},     {'/', 'o', '\370'},
--      {'`', 'U', '\331'},     {'`', 'u', '\371'},
--      {'\'', 'U', '\332'},    {'\'', 'u', '\372'},
--      {'^', 'U', '\333'},     {'^', 'u', '\373'},
--      {'"', 'U', '\334'},     {'"', 'u', '\374'},
--      {'\'', 'Y', '\335'},    {'\'', 'y', '\375'},
--      {'T', 'H', '\336'},     {'t', 'h', '\376'},
--      {'s', 's', '\337'},     {'"', 'y', '\377'},
--      {'s', 'z', '\337'},     {'i', 'j', '\377'},
-+      {'`', 'A', 0300},       {'`', 'a', 0340},
-+      {'\'', 'A', 0301},      {'\'', 'a', 0341},
-+      {'^', 'A', 0302},       {'^', 'a', 0342},
-+      {'~', 'A', 0303},       {'~', 'a', 0343},
-+      {'"', 'A', 0304},       {'"', 'a', 0344},
-+      {'O', 'A', 0305},       {'o', 'a', 0345},
-+      {'0', 'A', 0305},       {'0', 'a', 0345},
-+      {'A', 'A', 0305},       {'a', 'a', 0345},
-+      {'A', 'E', 0306},       {'a', 'e', 0346},
-+      {',', 'C', 0307},       {',', 'c', 0347},
-+      {'`', 'E', 0310},       {'`', 'e', 0350},
-+      {'\'', 'E', 0311},      {'\'', 'e', 0351},
-+      {'^', 'E', 0312},       {'^', 'e', 0352},
-+      {'"', 'E', 0313},       {'"', 'e', 0353},
-+      {'`', 'I', 0314},       {'`', 'i', 0354},
-+      {'\'', 'I', 0315},      {'\'', 'i', 0355},
-+      {'^', 'I', 0316},       {'^', 'i', 0356},
-+      {'"', 'I', 0317},       {'"', 'i', 0357},
-+      {'-', 'D', 0320},       {'-', 'd', 0360},
-+      {'~', 'N', 0321},       {'~', 'n', 0361},
-+      {'`', 'O', 0322},       {'`', 'o', 0362},
-+      {'\'', 'O', 0323},      {'\'', 'o', 0363},
-+      {'^', 'O', 0324},       {'^', 'o', 0364},
-+      {'~', 'O', 0325},       {'~', 'o', 0365},
-+      {'"', 'O', 0326},       {'"', 'o', 0366},
-+      {'/', 'O', 0330},       {'/', 'o', 0370},
-+      {'`', 'U', 0331},       {'`', 'u', 0371},
-+      {'\'', 'U', 0332},      {'\'', 'u', 0372},
-+      {'^', 'U', 0333},       {'^', 'u', 0373},
-+      {'"', 'U', 0334},       {'"', 'u', 0374},
-+      {'\'', 'Y', 0335},      {'\'', 'y', 0375},
-+      {'T', 'H', 0336},       {'t', 'h', 0376},
-+      {'s', 's', 0337},       {'"', 'y', 0377},
-+      {'s', 'z', 0337},       {'i', 'j', 0377},
- };
- unsigned int accent_table_size = 68;
-diff -Nurd linux-2.6.24/drivers/char/drm/drm_stub.c linux-2.6.24-oxe810/drivers/char/drm/drm_stub.c
---- linux-2.6.24/drivers/char/drm/drm_stub.c   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/char/drm/drm_stub.c    2008-06-11 17:49:50.000000000 +0200
-@@ -218,6 +218,7 @@
-       if (ret)
-               goto err_g1;
-+      pci_set_master(pdev);
-       if ((ret = drm_fill_in_dev(dev, pdev, ent, driver))) {
-               printk(KERN_ERR "DRM: Fill_in_dev failed.\n");
-               goto err_g2;
-diff -Nurd linux-2.6.24/drivers/char/drm/drm_vm.c linux-2.6.24-oxe810/drivers/char/drm/drm_vm.c
---- linux-2.6.24/drivers/char/drm/drm_vm.c     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/char/drm/drm_vm.c      2008-06-11 17:49:50.000000000 +0200
-@@ -506,6 +506,7 @@
-       vma->vm_ops = &drm_vm_dma_ops;
-       vma->vm_flags |= VM_RESERVED;   /* Don't swap */
-+      vma->vm_flags |= VM_DONTEXPAND;
-       vma->vm_file = filp;    /* Needed for drm_vm_open() */
-       drm_vm_open_locked(vma);
-@@ -655,6 +656,7 @@
-               return -EINVAL; /* This should never happen. */
-       }
-       vma->vm_flags |= VM_RESERVED;   /* Don't swap */
-+      vma->vm_flags |= VM_DONTEXPAND;
-       vma->vm_file = filp;    /* Needed for drm_vm_open() */
-       drm_vm_open_locked(vma);
-diff -Nurd linux-2.6.24/drivers/char/mspec.c linux-2.6.24-oxe810/drivers/char/mspec.c
---- linux-2.6.24/drivers/char/mspec.c  2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/char/mspec.c   2008-06-11 17:49:52.000000000 +0200
-@@ -283,7 +283,7 @@
-       vdata->refcnt = ATOMIC_INIT(1);
-       vma->vm_private_data = vdata;
--      vma->vm_flags |= (VM_IO | VM_RESERVED | VM_PFNMAP);
-+      vma->vm_flags |= (VM_IO | VM_RESERVED | VM_PFNMAP | VM_DONTEXPAND);
-       if (vdata->type == MSPEC_FETCHOP || vdata->type == MSPEC_UNCACHED)
-               vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-       vma->vm_ops = &mspec_vm_ops;
-diff -Nurd linux-2.6.24/drivers/char/vt.c linux-2.6.24-oxe810/drivers/char/vt.c
---- linux-2.6.24/drivers/char/vt.c     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/char/vt.c      2008-06-11 17:49:52.000000000 +0200
-@@ -702,6 +702,7 @@
-       if (is_switch) {
-               set_leds();
-               compute_shiftstate();
-+              notify_update(vc);
-       }
- }
-diff -Nurd linux-2.6.24/drivers/dma/Kconfig linux-2.6.24-oxe810/drivers/dma/Kconfig
---- linux-2.6.24/drivers/dma/Kconfig   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/dma/Kconfig    2008-06-11 17:49:45.000000000 +0200
-@@ -4,7 +4,7 @@
- menuconfig DMADEVICES
-       bool "DMA Engine support"
--      depends on (PCI && X86) || ARCH_IOP32X || ARCH_IOP33X || ARCH_IOP13XX
-+      depends on (PCI && X86) || ARCH_IOP32X || ARCH_IOP33X || ARCH_IOP13XX || ARCH_HIPOX
-       help
-         DMA engines can do asynchronous data transfers without
-         involving the host CPU.  Currently, this framework can be
-@@ -36,6 +36,14 @@
-       help
-         Enable support for the Intel(R) IOP Series RAID engines.
-+config HIPOX_ADMA
-+        tristate "Oxford Semiconductor ADAM support"
-+        depends on ARCH_HIPOX
-+      select ASYNC_CORE
-+      select DMA_ENGINE
-+        help
-+          Enable support for the Oxford Semiconductor async. DMA engine
-+
- config DMA_ENGINE
-       bool
-diff -Nurd linux-2.6.24/drivers/dma/Makefile linux-2.6.24-oxe810/drivers/dma/Makefile
---- linux-2.6.24/drivers/dma/Makefile  2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/dma/Makefile   2008-06-11 17:49:45.000000000 +0200
-@@ -3,3 +3,4 @@
- obj-$(CONFIG_INTEL_IOATDMA) += ioatdma.o
- ioatdma-objs := ioat.o ioat_dma.o ioat_dca.o
- obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o
-+obj-$(CONFIG_HIPOX_ADMA) += hipox_adma.o
-diff -Nurd linux-2.6.24/drivers/dma/ioat_dma.c linux-2.6.24-oxe810/drivers/dma/ioat_dma.c
---- linux-2.6.24/drivers/dma/ioat_dma.c        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/dma/ioat_dma.c 2008-06-11 17:49:45.000000000 +0200
-@@ -726,6 +726,7 @@
-       if (new) {
-               new->len = len;
-+              new->async_tx.ack = 0;
-               return &new->async_tx;
-       } else
-               return NULL;
-@@ -749,6 +750,7 @@
-       if (new) {
-               new->len = len;
-+              new->async_tx.ack = 0;
-               return &new->async_tx;
-       } else
-               return NULL;
-diff -Nurd linux-2.6.24/drivers/dma/hipox_adma.c linux-2.6.24-oxe810/drivers/dma/hipox_adma.c
---- linux-2.6.24/drivers/dma/hipox_adma.c      1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/dma/hipox_adma.c       2008-06-11 17:49:45.000000000 +0200
+diff -Nurd linux-2.6.24.4/drivers/dma/hipox_adma.c linux-2.6.24/drivers/dma/hipox_adma.c
+--- linux-2.6.24.4/drivers/dma/hipox_adma.c    1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/drivers/dma/hipox_adma.c      2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,272 @@
 +/*
 + * drivers/dma/hipox_adma.c
@@ -36571,50 +34709,44 @@ diff -Nurd linux-2.6.24/drivers/dma/hipox_adma.c linux-2.6.24-oxe810/drivers/dma
 +}
 +
 +module_exit(hipox_adma_exit_module);
-diff -Nurd linux-2.6.24/drivers/firmware/dmi_scan.c linux-2.6.24-oxe810/drivers/firmware/dmi_scan.c
---- linux-2.6.24/drivers/firmware/dmi_scan.c   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/firmware/dmi_scan.c    2008-06-11 17:49:40.000000000 +0200
-@@ -469,12 +469,3 @@
+diff -Nurd linux-2.6.24.4/drivers/dma/Kconfig linux-2.6.24/drivers/dma/Kconfig
+--- linux-2.6.24.4/drivers/dma/Kconfig 2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/drivers/dma/Kconfig   2010-01-14 14:01:15.000000000 +0100
+@@ -4,7 +4,7 @@
  
-       return year;
- }
--
--/**
-- *    dmi_get_slot - return dmi_ident[slot]
-- *    @slot:  index into dmi_ident[]
-- */
--char *dmi_get_slot(int slot)
--{
--      return(dmi_ident[slot]);
--}
-diff -Nurd linux-2.6.24/drivers/i2c/algos/Kconfig linux-2.6.24-oxe810/drivers/i2c/algos/Kconfig
---- linux-2.6.24/drivers/i2c/algos/Kconfig     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/i2c/algos/Kconfig      2008-06-11 17:50:33.000000000 +0200
-@@ -34,6 +34,10 @@
-         This support is also available as a module.  If so, the module 
-         will be called i2c-algo-pca.
+ menuconfig DMADEVICES
+       bool "DMA Engine support"
+-      depends on (PCI && X86) || ARCH_IOP32X || ARCH_IOP33X || ARCH_IOP13XX
++      depends on (PCI && X86) || ARCH_IOP32X || ARCH_IOP33X || ARCH_IOP13XX || ARCH_HIPOX
+       help
+         DMA engines can do asynchronous data transfers without
+         involving the host CPU.  Currently, this framework can be
+@@ -36,6 +36,14 @@
+       help
+         Enable support for the Intel(R) IOP Series RAID engines.
  
-+config I2C_ALGOOXSEMI
-+      tristate "HIPOX I2C interface"
-+      depends on I2C
++config HIPOX_ADMA
++        tristate "Oxford Semiconductor ADAM support"
++        depends on ARCH_HIPOX
++      select ASYNC_CORE
++      select DMA_ENGINE
++        help
++          Enable support for the Oxford Semiconductor async. DMA engine
 +
- config I2C_ALGO_SGI
-       tristate "I2C SGI interfaces"
-       depends on SGI_IP22 || SGI_IP32 || X86_VISWS
-diff -Nurd linux-2.6.24/drivers/i2c/algos/Makefile linux-2.6.24-oxe810/drivers/i2c/algos/Makefile
---- linux-2.6.24/drivers/i2c/algos/Makefile    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/i2c/algos/Makefile     2008-06-11 17:50:34.000000000 +0200
-@@ -5,6 +5,7 @@
- obj-$(CONFIG_I2C_ALGOBIT)     += i2c-algo-bit.o
- obj-$(CONFIG_I2C_ALGOPCF)     += i2c-algo-pcf.o
- obj-$(CONFIG_I2C_ALGOPCA)     += i2c-algo-pca.o
-+obj-$(CONFIG_I2C_ALGOOXSEMI)  += i2c-algo-hipox.o
- obj-$(CONFIG_I2C_ALGO_SGI)    += i2c-algo-sgi.o
+ config DMA_ENGINE
+       bool
  
- ifeq ($(CONFIG_I2C_DEBUG_ALGO),y)
-diff -Nurd linux-2.6.24/drivers/i2c/algos/i2c-algo-hipox.c linux-2.6.24-oxe810/drivers/i2c/algos/i2c-algo-hipox.c
---- linux-2.6.24/drivers/i2c/algos/i2c-algo-hipox.c    1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/i2c/algos/i2c-algo-hipox.c     2008-06-11 17:50:33.000000000 +0200
+diff -Nurd linux-2.6.24.4/drivers/dma/Makefile linux-2.6.24/drivers/dma/Makefile
+--- linux-2.6.24.4/drivers/dma/Makefile        2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/drivers/dma/Makefile  2010-01-14 14:01:15.000000000 +0100
+@@ -3,3 +3,4 @@
+ obj-$(CONFIG_INTEL_IOATDMA) += ioatdma.o
+ ioatdma-objs := ioat.o ioat_dma.o ioat_dca.o
+ obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o
++obj-$(CONFIG_HIPOX_ADMA) += hipox_adma.o
+diff -Nurd linux-2.6.24.4/drivers/i2c/algos/i2c-algo-hipox.c linux-2.6.24/drivers/i2c/algos/i2c-algo-hipox.c
+--- linux-2.6.24.4/drivers/i2c/algos/i2c-algo-hipox.c  1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/drivers/i2c/algos/i2c-algo-hipox.c    2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,858 @@
 +/*
 + * i2c-algo-hipox.c i2x driver algorithms for MPChipox 
@@ -37474,9 +35606,196 @@ diff -Nurd linux-2.6.24/drivers/i2c/algos/i2c-algo-hipox.c linux-2.6.24-oxe810/d
 +MODULE_DESCRIPTION("I2C-Bus hipox algorithm");
 +MODULE_LICENSE("GPL");
 +
-diff -Nurd linux-2.6.24/drivers/i2c/busses/Kconfig linux-2.6.24-oxe810/drivers/i2c/busses/Kconfig
---- linux-2.6.24/drivers/i2c/busses/Kconfig    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/i2c/busses/Kconfig     2008-06-11 17:50:33.000000000 +0200
+diff -Nurd linux-2.6.24.4/drivers/i2c/algos/Kconfig linux-2.6.24/drivers/i2c/algos/Kconfig
+--- linux-2.6.24.4/drivers/i2c/algos/Kconfig   2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/drivers/i2c/algos/Kconfig     2010-01-14 14:01:15.000000000 +0100
+@@ -34,6 +34,10 @@
+         This support is also available as a module.  If so, the module 
+         will be called i2c-algo-pca.
++config I2C_ALGOOXSEMI
++      tristate "HIPOX I2C interface"
++      depends on I2C
++
+ config I2C_ALGO_SGI
+       tristate "I2C SGI interfaces"
+       depends on SGI_IP22 || SGI_IP32 || X86_VISWS
+diff -Nurd linux-2.6.24.4/drivers/i2c/algos/Makefile linux-2.6.24/drivers/i2c/algos/Makefile
+--- linux-2.6.24.4/drivers/i2c/algos/Makefile  2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/drivers/i2c/algos/Makefile    2010-01-14 14:01:15.000000000 +0100
+@@ -5,6 +5,7 @@
+ obj-$(CONFIG_I2C_ALGOBIT)     += i2c-algo-bit.o
+ obj-$(CONFIG_I2C_ALGOPCF)     += i2c-algo-pcf.o
+ obj-$(CONFIG_I2C_ALGOPCA)     += i2c-algo-pca.o
++obj-$(CONFIG_I2C_ALGOOXSEMI)  += i2c-algo-hipox.o
+ obj-$(CONFIG_I2C_ALGO_SGI)    += i2c-algo-sgi.o
+ ifeq ($(CONFIG_I2C_DEBUG_ALGO),y)
+diff -Nurd linux-2.6.24.4/drivers/i2c/busses/i2c-hipox-bitbash.c linux-2.6.24/drivers/i2c/busses/i2c-hipox-bitbash.c
+--- linux-2.6.24.4/drivers/i2c/busses/i2c-hipox-bitbash.c      1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/drivers/i2c/busses/i2c-hipox-bitbash.c        2010-01-14 14:01:15.000000000 +0100
+@@ -0,0 +1,158 @@
++/*
++ * drivers/i2c/busses/i2c_hipox_bitbash.c
++ *
++ * Copyright (C) 2006-2008 Oxford Semiconductor Ltd
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/i2c.h>
++#include <linux/i2c-algo-bit.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++
++#define I2C_HIPOX_BITBASH_I2C_SDA_OUT   (1UL << (CONFIG_HIPOX_I2C_SDA))
++#define I2C_HIPOX_BITBASH_I2C_SCL_OUT   (1UL << (CONFIG_HIPOX_I2C_SCL))
++#define       I2C_HIPOX_BB_PULSEWIDTH (40)
++#define OPEN_COLLECTOR_CLOCK    1
++
++extern spinlock_t hipox_gpio_spinlock;
++
++static void i2c_hipox_bitbash_setsda(void *data,int state)
++{
++      if (state) {
++              // tristae as input to set line on bus
++              writel(I2C_HIPOX_BITBASH_I2C_SDA_OUT, GPIO_A_OUTPUT_ENABLE_CLEAR);
++      } else {
++              // tristate as output (with latch to zero) to assert zero on the bus
++              writel(I2C_HIPOX_BITBASH_I2C_SDA_OUT, GPIO_A_OUTPUT_CLEAR);
++              writel(I2C_HIPOX_BITBASH_I2C_SDA_OUT, GPIO_A_OUTPUT_ENABLE_SET);
++      }
++}
++
++static void i2c_hipox_bitbash_setscl(void *data,int state)
++{
++#if OPEN_COLLECTOR_CLOCK
++      if (state) {
++              // tristae as input to set line on bus
++              writel(I2C_HIPOX_BITBASH_I2C_SCL_OUT, GPIO_A_OUTPUT_ENABLE_CLEAR);
++      } else {
++              // tristate as output (with latch to zero) to assert zero on the bus
++              writel(I2C_HIPOX_BITBASH_I2C_SCL_OUT, GPIO_A_OUTPUT_CLEAR);
++              writel(I2C_HIPOX_BITBASH_I2C_SCL_OUT, GPIO_A_OUTPUT_ENABLE_SET);
++      }
++#else // driven clock
++      if (state) {
++              // tristae as input to set line on bus
++              writel(I2C_HIPOX_BITBASH_I2C_SCL_OUT, GPIO_A_OUTPUT_SET);
++              writel(I2C_HIPOX_BITBASH_I2C_SCL_OUT, GPIO_A_OUTPUT_ENABLE_CLEAR);
++      } else {
++              // tristate as output (with latch to zero) to assert zero on the bus
++              writel(I2C_HIPOX_BITBASH_I2C_SCL_OUT, GPIO_A_OUTPUT_CLEAR);
++              writel(I2C_HIPOX_BITBASH_I2C_SCL_OUT, GPIO_A_OUTPUT_ENABLE_SET);
++      }
++
++#endif
++}
++
++static int i2c_hipox_bitbash_getsda(void *data)
++{
++      return ((readl(GPIO_A_DATA ) & I2C_HIPOX_BITBASH_I2C_SDA_OUT) != 0);
++}
++
++static int i2c_hipox_bitbash_getscl(void *data)
++{
++      return ((readl(GPIO_A_DATA ) & I2C_HIPOX_BITBASH_I2C_SCL_OUT) != 0);
++}
++
++static struct i2c_algo_bit_data bit_i2c_hipox_bitbash_data = {
++      .setsda    = i2c_hipox_bitbash_setsda,
++      .setscl    = i2c_hipox_bitbash_setscl,
++      .getsda    = i2c_hipox_bitbash_getsda,
++      .getscl    = i2c_hipox_bitbash_getscl,
++      .udelay    = I2C_HIPOX_BB_PULSEWIDTH,
++      .timeout   = HZ
++};
++
++static struct i2c_adapter hipox_i2c_bitbash_adapter = {
++      .owner          = THIS_MODULE,
++      .name           = "i2c_hipox_bitbash adapter driver",
++      .id                 = I2C_HW_B_HIPOX,
++      .algo_data      = &bit_i2c_hipox_bitbash_data,
++};
++
++static int __init i2c_hipox_bitbash_init(void)
++{
++    unsigned long flags;
++    unsigned long mask = I2C_HIPOX_BITBASH_I2C_SDA_OUT | I2C_HIPOX_BITBASH_I2C_SCL_OUT;
++      int ret = 0;
++
++      /* Dedicate the GPIO over to i2c.
++     * NOTE: This may be confusing, but we are not using the i2c core here we
++     * are using bit-bashed GPIO, so we must disable the primary, secondary and
++     * tertiary functions of the relevant GPIO pins
++     */
++    spin_lock_irqsave(&hipox_gpio_spinlock, flags);
++    writel(readl(SYS_CTRL_GPIO_PRIMSEL_CTRL_0) & ~mask, SYS_CTRL_GPIO_PRIMSEL_CTRL_0);
++    writel(readl(SYS_CTRL_GPIO_SECSEL_CTRL_0)  & ~mask, SYS_CTRL_GPIO_SECSEL_CTRL_0);
++    writel(readl(SYS_CTRL_GPIO_TERTSEL_CTRL_0) & ~mask, SYS_CTRL_GPIO_TERTSEL_CTRL_0);
++    spin_unlock_irqrestore(&hipox_gpio_spinlock, flags);
++
++      i2c_hipox_bitbash_setsda(NULL, 1);
++      i2c_hipox_bitbash_setscl(NULL, 1);
++      ret = i2c_bit_add_bus(&hipox_i2c_bitbash_adapter);
++      if (!ret) {
++#if defined(CONFIG_HIPOX_RTC) || defined(CONFIG_HIPOX_RTC_MODULE)
++              /* Register the ST MT4100 RTC */
++              struct i2c_board_info rtc_info  = {
++                      .driver_name   = "rtc-ds1307",
++                      .type          = "m41t00",
++                      .flags         = 0,
++                      .addr          = 0x68,
++                      .platform_data = NULL,
++                      .irq           = 0
++              };
++
++              struct i2c_client *client = i2c_new_device(&hipox_i2c_bitbash_adapter, &rtc_info);
++              if (!client) {
++                      printk(KERN_WARNING "HIPOX bit-bash I2C driver failed to register RTC device\n");
++                      ret = -EIO;
++              }
++#endif // CONFIG_HIPOX_RTC || CONFIG_HIPOX_RTC_MODULE
++      }
++
++      printk(KERN_INFO "HIPOX bit-bash I2C driver initialisation %s\n", ret ? "failed": "OK");
++      return ret;
++}
++
++static void __exit i2c_hipox_bitbash_exit(void)
++{
++      i2c_hipox_bitbash_setsda(NULL, 1);
++      i2c_hipox_bitbash_setscl(NULL, 1);
++      i2c_del_adapter(&hipox_i2c_bitbash_adapter);
++}
++
++MODULE_AUTHOR("Brian Clarke");
++MODULE_DESCRIPTION("HIPOX bit-bash I2C bus driver");
++MODULE_LICENSE("GPL");
++MODULE_VERSION("v2.0");
++
++module_init (i2c_hipox_bitbash_init);
++module_exit (i2c_hipox_bitbash_exit);
++
+diff -Nurd linux-2.6.24.4/drivers/i2c/busses/Kconfig linux-2.6.24/drivers/i2c/busses/Kconfig
+--- linux-2.6.24.4/drivers/i2c/busses/Kconfig  2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/drivers/i2c/busses/Kconfig    2010-01-14 14:01:15.000000000 +0100
 @@ -321,6 +321,15 @@
          This driver can also be built as a module.  If so, the module
          will be called i2c-nforce2.
@@ -37493,9 +35812,9 @@ diff -Nurd linux-2.6.24/drivers/i2c/busses/Kconfig linux-2.6.24-oxe810/drivers/i
  config I2C_OCORES
        tristate "OpenCores I2C Controller"
        depends on EXPERIMENTAL
-diff -Nurd linux-2.6.24/drivers/i2c/busses/Makefile linux-2.6.24-oxe810/drivers/i2c/busses/Makefile
---- linux-2.6.24/drivers/i2c/busses/Makefile   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/i2c/busses/Makefile    2008-06-11 17:50:33.000000000 +0200
+diff -Nurd linux-2.6.24.4/drivers/i2c/busses/Makefile linux-2.6.24/drivers/i2c/busses/Makefile
+--- linux-2.6.24.4/drivers/i2c/busses/Makefile 2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/drivers/i2c/busses/Makefile   2010-01-14 14:01:15.000000000 +0100
 @@ -28,6 +28,7 @@
  obj-$(CONFIG_I2C_OCORES)      += i2c-ocores.o
  obj-$(CONFIG_I2C_OMAP)                += i2c-omap.o
@@ -37504,171 +35823,9 @@ diff -Nurd linux-2.6.24/drivers/i2c/busses/Makefile linux-2.6.24-oxe810/drivers/
  obj-$(CONFIG_I2C_PARPORT_LIGHT)       += i2c-parport-light.o
  obj-$(CONFIG_I2C_PASEMI)      += i2c-pasemi.o
  obj-$(CONFIG_I2C_PCA_ISA)     += i2c-pca-isa.o
-diff -Nurd linux-2.6.24/drivers/i2c/busses/i2c-hipox-bitbash.c linux-2.6.24-oxe810/drivers/i2c/busses/i2c-hipox-bitbash.c
---- linux-2.6.24/drivers/i2c/busses/i2c-hipox-bitbash.c        1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/i2c/busses/i2c-hipox-bitbash.c 2008-06-11 17:50:33.000000000 +0200
-@@ -0,0 +1,158 @@
-+/*
-+ * drivers/i2c/busses/i2c_hipox_bitbash.c
-+ *
-+ * Copyright (C) 2006-2008 Oxford Semiconductor Ltd
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/delay.h>
-+#include <linux/i2c.h>
-+#include <linux/i2c-algo-bit.h>
-+#include <asm/hardware.h>
-+#include <asm/io.h>
-+
-+#define I2C_HIPOX_BITBASH_I2C_SDA_OUT   (1UL << (CONFIG_HIPOX_I2C_SDA))
-+#define I2C_HIPOX_BITBASH_I2C_SCL_OUT   (1UL << (CONFIG_HIPOX_I2C_SCL))
-+#define       I2C_HIPOX_BB_PULSEWIDTH (40)
-+#define OPEN_COLLECTOR_CLOCK    1
-+
-+extern spinlock_t hipox_gpio_spinlock;
-+
-+static void i2c_hipox_bitbash_setsda(void *data,int state)
-+{
-+      if (state) {
-+              // tristae as input to set line on bus
-+              writel(I2C_HIPOX_BITBASH_I2C_SDA_OUT, GPIO_A_OUTPUT_ENABLE_CLEAR);
-+      } else {
-+              // tristate as output (with latch to zero) to assert zero on the bus
-+              writel(I2C_HIPOX_BITBASH_I2C_SDA_OUT, GPIO_A_OUTPUT_CLEAR);
-+              writel(I2C_HIPOX_BITBASH_I2C_SDA_OUT, GPIO_A_OUTPUT_ENABLE_SET);
-+      }
-+}
-+
-+static void i2c_hipox_bitbash_setscl(void *data,int state)
-+{
-+#if OPEN_COLLECTOR_CLOCK
-+      if (state) {
-+              // tristae as input to set line on bus
-+              writel(I2C_HIPOX_BITBASH_I2C_SCL_OUT, GPIO_A_OUTPUT_ENABLE_CLEAR);
-+      } else {
-+              // tristate as output (with latch to zero) to assert zero on the bus
-+              writel(I2C_HIPOX_BITBASH_I2C_SCL_OUT, GPIO_A_OUTPUT_CLEAR);
-+              writel(I2C_HIPOX_BITBASH_I2C_SCL_OUT, GPIO_A_OUTPUT_ENABLE_SET);
-+      }
-+#else // driven clock
-+      if (state) {
-+              // tristae as input to set line on bus
-+              writel(I2C_HIPOX_BITBASH_I2C_SCL_OUT, GPIO_A_OUTPUT_SET);
-+              writel(I2C_HIPOX_BITBASH_I2C_SCL_OUT, GPIO_A_OUTPUT_ENABLE_CLEAR);
-+      } else {
-+              // tristate as output (with latch to zero) to assert zero on the bus
-+              writel(I2C_HIPOX_BITBASH_I2C_SCL_OUT, GPIO_A_OUTPUT_CLEAR);
-+              writel(I2C_HIPOX_BITBASH_I2C_SCL_OUT, GPIO_A_OUTPUT_ENABLE_SET);
-+      }
-+
-+#endif
-+}
-+
-+static int i2c_hipox_bitbash_getsda(void *data)
-+{
-+      return ((readl(GPIO_A_DATA ) & I2C_HIPOX_BITBASH_I2C_SDA_OUT) != 0);
-+}
-+
-+static int i2c_hipox_bitbash_getscl(void *data)
-+{
-+      return ((readl(GPIO_A_DATA ) & I2C_HIPOX_BITBASH_I2C_SCL_OUT) != 0);
-+}
-+
-+static struct i2c_algo_bit_data bit_i2c_hipox_bitbash_data = {
-+      .setsda    = i2c_hipox_bitbash_setsda,
-+      .setscl    = i2c_hipox_bitbash_setscl,
-+      .getsda    = i2c_hipox_bitbash_getsda,
-+      .getscl    = i2c_hipox_bitbash_getscl,
-+      .udelay    = I2C_HIPOX_BB_PULSEWIDTH,
-+      .timeout   = HZ
-+};
-+
-+static struct i2c_adapter hipox_i2c_bitbash_adapter = {
-+      .owner          = THIS_MODULE,
-+      .name           = "i2c_hipox_bitbash adapter driver",
-+      .id                 = I2C_HW_B_HIPOX,
-+      .algo_data      = &bit_i2c_hipox_bitbash_data,
-+};
-+
-+static int __init i2c_hipox_bitbash_init(void)
-+{
-+    unsigned long flags;
-+    unsigned long mask = I2C_HIPOX_BITBASH_I2C_SDA_OUT | I2C_HIPOX_BITBASH_I2C_SCL_OUT;
-+      int ret = 0;
-+
-+      /* Dedicate the GPIO over to i2c.
-+     * NOTE: This may be confusing, but we are not using the i2c core here we
-+     * are using bit-bashed GPIO, so we must disable the primary, secondary and
-+     * tertiary functions of the relevant GPIO pins
-+     */
-+    spin_lock_irqsave(&hipox_gpio_spinlock, flags);
-+    writel(readl(SYS_CTRL_GPIO_PRIMSEL_CTRL_0) & ~mask, SYS_CTRL_GPIO_PRIMSEL_CTRL_0);
-+    writel(readl(SYS_CTRL_GPIO_SECSEL_CTRL_0)  & ~mask, SYS_CTRL_GPIO_SECSEL_CTRL_0);
-+    writel(readl(SYS_CTRL_GPIO_TERTSEL_CTRL_0) & ~mask, SYS_CTRL_GPIO_TERTSEL_CTRL_0);
-+    spin_unlock_irqrestore(&hipox_gpio_spinlock, flags);
-+
-+      i2c_hipox_bitbash_setsda(NULL, 1);
-+      i2c_hipox_bitbash_setscl(NULL, 1);
-+      ret = i2c_bit_add_bus(&hipox_i2c_bitbash_adapter);
-+      if (!ret) {
-+#if defined(CONFIG_HIPOX_RTC) || defined(CONFIG_HIPOX_RTC_MODULE)
-+              /* Register the ST MT4100 RTC */
-+              struct i2c_board_info rtc_info  = {
-+                      .driver_name   = "rtc-ds1307",
-+                      .type          = "m41t00",
-+                      .flags         = 0,
-+                      .addr          = 0x68,
-+                      .platform_data = NULL,
-+                      .irq           = 0
-+              };
-+
-+              struct i2c_client *client = i2c_new_device(&hipox_i2c_bitbash_adapter, &rtc_info);
-+              if (!client) {
-+                      printk(KERN_WARNING "HIPOX bit-bash I2C driver failed to register RTC device\n");
-+                      ret = -EIO;
-+              }
-+#endif // CONFIG_HIPOX_RTC || CONFIG_HIPOX_RTC_MODULE
-+      }
-+
-+      printk(KERN_INFO "HIPOX bit-bash I2C driver initialisation %s\n", ret ? "failed": "OK");
-+      return ret;
-+}
-+
-+static void __exit i2c_hipox_bitbash_exit(void)
-+{
-+      i2c_hipox_bitbash_setsda(NULL, 1);
-+      i2c_hipox_bitbash_setscl(NULL, 1);
-+      i2c_del_adapter(&hipox_i2c_bitbash_adapter);
-+}
-+
-+MODULE_AUTHOR("Brian Clarke");
-+MODULE_DESCRIPTION("HIPOX bit-bash I2C bus driver");
-+MODULE_LICENSE("GPL");
-+MODULE_VERSION("v2.0");
-+
-+module_init (i2c_hipox_bitbash_init);
-+module_exit (i2c_hipox_bitbash_exit);
-+
-diff -Nurd linux-2.6.24/drivers/leds/Kconfig linux-2.6.24-oxe810/drivers/leds/Kconfig
---- linux-2.6.24/drivers/leds/Kconfig  2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/leds/Kconfig   2008-06-11 17:50:12.000000000 +0200
+diff -Nurd linux-2.6.24.4/drivers/leds/Kconfig linux-2.6.24/drivers/leds/Kconfig
+--- linux-2.6.24.4/drivers/leds/Kconfig        2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/drivers/leds/Kconfig  2010-01-14 14:01:15.000000000 +0100
 @@ -62,6 +62,20 @@
          This option enables support for LEDs connected to GPIO lines
          on Samsung S3C24XX series CPUs, such as the S3C2410 and S3C2440.
@@ -37704,109 +35861,9 @@ diff -Nurd linux-2.6.24/drivers/leds/Kconfig linux-2.6.24-oxe810/drivers/leds/Kc
  config LEDS_TRIGGER_HEARTBEAT
        tristate "LED Heartbeat Trigger"
        depends on LEDS_TRIGGERS
-diff -Nurd linux-2.6.24/drivers/macintosh/smu.c linux-2.6.24-oxe810/drivers/macintosh/smu.c
---- linux-2.6.24/drivers/macintosh/smu.c       2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/macintosh/smu.c        2008-06-11 17:49:30.000000000 +0200
-@@ -85,6 +85,7 @@
-       u32                     cmd_buf_abs;    /* command buffer absolute */
-       struct list_head        cmd_list;
-       struct smu_cmd          *cmd_cur;       /* pending command */
-+      int                     broken_nap;
-       struct list_head        cmd_i2c_list;
-       struct smu_i2c_cmd      *cmd_i2c_cur;   /* pending i2c command */
-       struct timer_list       i2c_timer;
-@@ -135,6 +136,19 @@
-       fend = faddr + smu->cmd_buf->length + 2;
-       flush_inval_dcache_range(faddr, fend);
-+
-+      /* We also disable NAP mode for the duration of the command
-+       * on U3 based machines.
-+       * This is slightly racy as it can be written back to 1 by a sysctl
-+       * but that never happens in practice. There seem to be an issue with
-+       * U3 based machines such as the iMac G5 where napping for the
-+       * whole duration of the command prevents the SMU from fetching it
-+       * from memory. This might be related to the strange i2c based
-+       * mechanism the SMU uses to access memory.
-+       */
-+      if (smu->broken_nap)
-+              powersave_nap = 0;
-+
-       /* This isn't exactly a DMA mapping here, I suspect
-        * the SMU is actually communicating with us via i2c to the
-        * northbridge or the CPU to access RAM.
-@@ -211,6 +225,10 @@
-       misc = cmd->misc;
-       mb();
-       cmd->status = rc;
-+
-+      /* Re-enable NAP mode */
-+      if (smu->broken_nap)
-+              powersave_nap = 1;
-  bail:
-       /* Start next command if any */
-       smu_start_cmd();
-@@ -461,7 +479,7 @@
-         if (np == NULL)
-               return -ENODEV;
--      printk(KERN_INFO "SMU driver %s %s\n", VERSION, AUTHOR);
-+      printk(KERN_INFO "SMU: Driver %s %s\n", VERSION, AUTHOR);
-       if (smu_cmdbuf_abs == 0) {
-               printk(KERN_ERR "SMU: Command buffer not allocated !\n");
-@@ -533,6 +551,11 @@
-               goto fail;
-       }
-+      /* U3 has an issue with NAP mode when issuing SMU commands */
-+      smu->broken_nap = pmac_get_uninorth_variant() < 4;
-+      if (smu->broken_nap)
-+              printk(KERN_INFO "SMU: using NAP mode workaround\n");
-+
-       sys_ctrler = SYS_CTRLER_SMU;
-       return 0;
-diff -Nurd linux-2.6.24/drivers/md/Kconfig linux-2.6.24-oxe810/drivers/md/Kconfig
---- linux-2.6.24/drivers/md/Kconfig    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/md/Kconfig     2008-06-11 17:50:20.000000000 +0200
-@@ -229,6 +229,22 @@
-         If unsure, say N.
-+config DM_OX_CRYPT
-+      tristate "OX800 Hardware Cryptograpy target support"
-+      depends on BLK_DEV_DM && EXPERIMENTAL && CRYPTO_OXAESLRW
-+      ---help---
-+      Based on dm-crypt by Fruhwirth & Saout it has been modified
-+      to work with the LRW-AES core in the OX800 NAS chip from
-+      Oxford Semiconductor Ltd.
-+      
-+        This device-mapper target allows you to create a device that
-+        transparently encrypts the data on it.
-+      
-+        To compile this code as a module, choose M here: the module will
-+        be called dm-ox-crypt.
-+
-+        If unsure, say N.
-+
- config DM_SNAPSHOT
-        tristate "Snapshot target (EXPERIMENTAL)"
-        depends on BLK_DEV_DM && EXPERIMENTAL
-diff -Nurd linux-2.6.24/drivers/md/Makefile linux-2.6.24-oxe810/drivers/md/Makefile
---- linux-2.6.24/drivers/md/Makefile   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/md/Makefile    2008-06-11 17:50:20.000000000 +0200
-@@ -33,6 +33,7 @@
- obj-$(CONFIG_BLK_DEV_MD)      += md-mod.o
- obj-$(CONFIG_BLK_DEV_DM)      += dm-mod.o
- obj-$(CONFIG_DM_CRYPT)                += dm-crypt.o
-+obj-$(CONFIG_DM_OX_CRYPT)   += dm-ox-crypt.o
- obj-$(CONFIG_DM_DELAY)                += dm-delay.o
- obj-$(CONFIG_DM_MULTIPATH)    += dm-multipath.o dm-round-robin.o
- obj-$(CONFIG_DM_MULTIPATH_EMC)        += dm-emc.o
-diff -Nurd linux-2.6.24/drivers/md/dm-ox-crypt.c linux-2.6.24-oxe810/drivers/md/dm-ox-crypt.c
---- linux-2.6.24/drivers/md/dm-ox-crypt.c      1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/md/dm-ox-crypt.c       2008-06-11 17:50:20.000000000 +0200
+diff -Nurd linux-2.6.24.4/drivers/md/dm-ox-crypt.c linux-2.6.24/drivers/md/dm-ox-crypt.c
+--- linux-2.6.24.4/drivers/md/dm-ox-crypt.c    1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/drivers/md/dm-ox-crypt.c      2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,791 @@
 +/* linux/drivers/md/dm-ox-crypt.c
 + *
@@ -38599,9 +36656,46 @@ diff -Nurd linux-2.6.24/drivers/md/dm-ox-crypt.c linux-2.6.24-oxe810/drivers/md/
 +MODULE_AUTHOR("Oxford Semiconductor based on work of Christophe Saout");
 +MODULE_DESCRIPTION(DM_NAME " target for hardware encryption / decryption");
 +MODULE_LICENSE("GPL");
-diff -Nurd linux-2.6.24/drivers/md/raid1.c linux-2.6.24-oxe810/drivers/md/raid1.c
---- linux-2.6.24/drivers/md/raid1.c    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/md/raid1.c     2008-06-11 17:50:20.000000000 +0200
+diff -Nurd linux-2.6.24.4/drivers/md/Kconfig linux-2.6.24/drivers/md/Kconfig
+--- linux-2.6.24.4/drivers/md/Kconfig  2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/drivers/md/Kconfig    2010-01-14 14:01:15.000000000 +0100
+@@ -229,6 +229,22 @@
+         If unsure, say N.
++config DM_OX_CRYPT
++      tristate "OX800 Hardware Cryptograpy target support"
++      depends on BLK_DEV_DM && EXPERIMENTAL && CRYPTO_OXAESLRW
++      ---help---
++      Based on dm-crypt by Fruhwirth & Saout it has been modified
++      to work with the LRW-AES core in the OX800 NAS chip from
++      Oxford Semiconductor Ltd.
++      
++        This device-mapper target allows you to create a device that
++        transparently encrypts the data on it.
++      
++        To compile this code as a module, choose M here: the module will
++        be called dm-ox-crypt.
++
++        If unsure, say N.
++
+ config DM_SNAPSHOT
+        tristate "Snapshot target (EXPERIMENTAL)"
+        depends on BLK_DEV_DM && EXPERIMENTAL
+diff -Nurd linux-2.6.24.4/drivers/md/Makefile linux-2.6.24/drivers/md/Makefile
+--- linux-2.6.24.4/drivers/md/Makefile 2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/drivers/md/Makefile   2010-01-14 14:01:15.000000000 +0100
+@@ -33,6 +33,7 @@
+ obj-$(CONFIG_BLK_DEV_MD)      += md-mod.o
+ obj-$(CONFIG_BLK_DEV_DM)      += dm-mod.o
+ obj-$(CONFIG_DM_CRYPT)                += dm-crypt.o
++obj-$(CONFIG_DM_OX_CRYPT)   += dm-ox-crypt.o
+ obj-$(CONFIG_DM_DELAY)                += dm-delay.o
+ obj-$(CONFIG_DM_MULTIPATH)    += dm-multipath.o dm-round-robin.o
+ obj-$(CONFIG_DM_MULTIPATH_EMC)        += dm-emc.o
+diff -Nurd linux-2.6.24.4/drivers/md/raid1.c linux-2.6.24/drivers/md/raid1.c
+--- linux-2.6.24.4/drivers/md/raid1.c  2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/drivers/md/raid1.c    2010-01-14 14:01:15.000000000 +0100
 @@ -34,6 +34,12 @@
  #include "dm-bio-list.h"
  #include <linux/raid/raid1.h>
@@ -38865,38 +36959,9 @@ diff -Nurd linux-2.6.24/drivers/md/raid1.c linux-2.6.24-oxe810/drivers/md/raid1.
        lower_barrier(conf);
  
        set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
-diff -Nurd linux-2.6.24/drivers/media/video/cx23885/cx23885-cards.c linux-2.6.24-oxe810/drivers/media/video/cx23885/cx23885-cards.c
---- linux-2.6.24/drivers/media/video/cx23885/cx23885-cards.c   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/media/video/cx23885/cx23885-cards.c    2008-06-11 17:48:59.000000000 +0200
-@@ -138,6 +138,10 @@
-               .card      = CX23885_BOARD_HAUPPAUGE_HVR1800,
-       },{
-               .subvendor = 0x0070,
-+              .subdevice = 0x7809,
-+              .card      = CX23885_BOARD_HAUPPAUGE_HVR1800,
-+      },{
-+              .subvendor = 0x0070,
-               .subdevice = 0x7911,
-               .card      = CX23885_BOARD_HAUPPAUGE_HVR1250,
-       },{
-diff -Nurd linux-2.6.24/drivers/message/fusion/mptsas.c linux-2.6.24-oxe810/drivers/message/fusion/mptsas.c
---- linux-2.6.24/drivers/message/fusion/mptsas.c       2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/message/fusion/mptsas.c        2008-06-11 17:49:11.000000000 +0200
-@@ -1699,6 +1699,11 @@
-       if (error)
-               goto out_free_consistent;
-+      if (!buffer->NumPhys) {
-+              error = -ENODEV;
-+              goto out_free_consistent;
-+      }
-+
-       /* save config data */
-       port_info->num_phys = buffer->NumPhys;
-       port_info->phy_info = kcalloc(port_info->num_phys,
-diff -Nurd linux-2.6.24/drivers/net/Kconfig linux-2.6.24-oxe810/drivers/net/Kconfig
---- linux-2.6.24/drivers/net/Kconfig   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/net/Kconfig    2008-06-11 17:50:11.000000000 +0200
+diff -Nurd linux-2.6.24.4/drivers/net/Kconfig linux-2.6.24/drivers/net/Kconfig
+--- linux-2.6.24.4/drivers/net/Kconfig 2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/drivers/net/Kconfig   2010-01-14 14:01:15.000000000 +0100
 @@ -2368,6 +2368,14 @@
          To compile this driver as a module, choose M here.  The module
          will be called atl1.
@@ -38912,132 +36977,9 @@ diff -Nurd linux-2.6.24/drivers/net/Kconfig linux-2.6.24-oxe810/drivers/net/Kcon
  endif # NETDEV_1000
  
  #
-diff -Nurd linux-2.6.24/drivers/net/bonding/bond_main.c linux-2.6.24-oxe810/drivers/net/bonding/bond_main.c
---- linux-2.6.24/drivers/net/bonding/bond_main.c       2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/net/bonding/bond_main.c        2008-06-11 17:50:00.000000000 +0200
-@@ -4883,14 +4883,16 @@
-       down_write(&bonding_rwsem);
-       /* Check to see if the bond already exists. */
--      list_for_each_entry_safe(bond, nxt, &bond_dev_list, bond_list)
--              if (strnicmp(bond->dev->name, name, IFNAMSIZ) == 0) {
--                      printk(KERN_ERR DRV_NAME
-+      if (name) {
-+              list_for_each_entry_safe(bond, nxt, &bond_dev_list, bond_list)
-+                      if (strnicmp(bond->dev->name, name, IFNAMSIZ) == 0) {
-+                              printk(KERN_ERR DRV_NAME
-                              ": cannot add bond %s; it already exists\n",
--                             name);
--                      res = -EPERM;
--                      goto out_rtnl;
--              }
-+                                     name);
-+                              res = -EPERM;
-+                              goto out_rtnl;
-+                      }
-+      }
-       bond_dev = alloc_netdev(sizeof(struct bonding), name ? name : "",
-                               ether_setup);
-diff -Nurd linux-2.6.24/drivers/net/dl2k.h linux-2.6.24-oxe810/drivers/net/dl2k.h
---- linux-2.6.24/drivers/net/dl2k.h    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/net/dl2k.h     2008-06-11 17:50:11.000000000 +0200
-@@ -388,8 +388,8 @@
-       MII_MSSR_CFG_RES = 0x4000,
-       MII_MSSR_LOCAL_RCV_STATUS = 0x2000,
-       MII_MSSR_REMOTE_RCVR = 0x1000,
--      MII_MSSR_LP_1000BT_HD = 0x0800,
--      MII_MSSR_LP_1000BT_FD = 0x0400,
-+      MII_MSSR_LP_1000BT_FD = 0x0800,
-+      MII_MSSR_LP_1000BT_HD = 0x0400,
-       MII_MSSR_IDLE_ERR_COUNT = 0x00ff,
- };
-diff -Nurd linux-2.6.24/drivers/net/e1000e/netdev.c linux-2.6.24-oxe810/drivers/net/e1000e/netdev.c
---- linux-2.6.24/drivers/net/e1000e/netdev.c   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/net/e1000e/netdev.c    2008-06-11 17:50:07.000000000 +0200
-@@ -1686,6 +1686,9 @@
-       else
-               rctl |= E1000_RCTL_LPE;
-+      /* Enable hardware CRC frame stripping */
-+      rctl |= E1000_RCTL_SECRC;
-+
-       /* Setup buffer sizes */
-       rctl &= ~E1000_RCTL_SZ_4096;
-       rctl |= E1000_RCTL_BSEX;
-@@ -1751,9 +1754,6 @@
-               /* Enable Packet split descriptors */
-               rctl |= E1000_RCTL_DTYP_PS;
--              
--              /* Enable hardware CRC frame stripping */
--              rctl |= E1000_RCTL_SECRC;
-               psrctl |= adapter->rx_ps_bsize0 >>
-                       E1000_PSRCTL_BSIZE0_SHIFT;
-diff -Nurd linux-2.6.24/drivers/net/forcedeth.c linux-2.6.24-oxe810/drivers/net/forcedeth.c
---- linux-2.6.24/drivers/net/forcedeth.c       2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/net/forcedeth.c        2008-06-11 17:50:11.000000000 +0200
-@@ -5593,35 +5593,35 @@
-       },
-       {       /* MCP77 Ethernet Controller */
-               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_32),
--              .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
-+              .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
-       },
-       {       /* MCP77 Ethernet Controller */
-               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_33),
--              .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
-+              .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
-       },
-       {       /* MCP77 Ethernet Controller */
-               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_34),
--              .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
-+              .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
-       },
-       {       /* MCP77 Ethernet Controller */
-               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_35),
--              .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
-+              .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
-       },
-       {       /* MCP79 Ethernet Controller */
-               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_36),
--              .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
-+              .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
-       },
-       {       /* MCP79 Ethernet Controller */
-               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_37),
--              .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
-+              .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
-       },
-       {       /* MCP79 Ethernet Controller */
-               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_38),
--              .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
-+              .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
-       },
-       {       /* MCP79 Ethernet Controller */
-               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_39),
--              .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
-+              .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
-       },
-       {0,},
- };
-diff -Nurd linux-2.6.24/drivers/net/macb.c linux-2.6.24-oxe810/drivers/net/macb.c
---- linux-2.6.24/drivers/net/macb.c    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/net/macb.c     2008-06-11 17:50:11.000000000 +0200
-@@ -148,7 +148,7 @@
-                       if (phydev->duplex)
-                               reg |= MACB_BIT(FD);
--                      if (phydev->speed)
-+                      if (phydev->speed == SPEED_100)
-                               reg |= MACB_BIT(SPD);
-                       macb_writel(bp, NCFGR, reg);
-diff -Nurd linux-2.6.24/drivers/net/mii.c linux-2.6.24-oxe810/drivers/net/mii.c
---- linux-2.6.24/drivers/net/mii.c     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/net/mii.c      2008-06-11 17:50:11.000000000 +0200
+diff -Nurd linux-2.6.24.4/drivers/net/mii.c linux-2.6.24/drivers/net/mii.c
+--- linux-2.6.24.4/drivers/net/mii.c   2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/drivers/net/mii.c     2010-01-14 14:01:15.000000000 +0100
 @@ -46,11 +46,13 @@
        u32 advert, bmcr, lpa, nego;
        u32 advert2 = 0, bmcr2 = 0, lpa2 = 0;
@@ -39290,175 +37232,9 @@ diff -Nurd linux-2.6.24/drivers/net/mii.c linux-2.6.24-oxe810/drivers/net/mii.c
  EXPORT_SYMBOL(mii_check_gmii_support);
  EXPORT_SYMBOL(generic_mii_ioctl);
  
-diff -Nurd linux-2.6.24/drivers/net/niu.c linux-2.6.24-oxe810/drivers/net/niu.c
---- linux-2.6.24/drivers/net/niu.c     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/net/niu.c      2008-06-11 17:50:11.000000000 +0200
-@@ -33,8 +33,8 @@
- #define DRV_MODULE_NAME               "niu"
- #define PFX DRV_MODULE_NAME   ": "
--#define DRV_MODULE_VERSION    "0.6"
--#define DRV_MODULE_RELDATE    "January 5, 2008"
-+#define DRV_MODULE_VERSION    "0.7"
-+#define DRV_MODULE_RELDATE    "February 18, 2008"
- static char version[] __devinitdata =
-       DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
-@@ -1616,12 +1616,13 @@
-       if (index >= niu_num_alt_addr(np))
-               return -EINVAL;
--      if (np->flags & NIU_FLAGS_XMAC)
-+      if (np->flags & NIU_FLAGS_XMAC) {
-               reg = XMAC_ADDR_CMPEN;
--      else
-+              mask = 1 << index;
-+      } else {
-               reg = BMAC_ADDR_CMPEN;
--
--      mask = 1 << index;
-+              mask = 1 << (index + 1);
-+      }
-       val = nr64_mac(reg);
-       if (on)
-@@ -5147,7 +5148,12 @@
-                       index++;
-               }
-       } else {
--              for (i = 0; i < niu_num_alt_addr(np); i++) {
-+              int alt_start;
-+              if (np->flags & NIU_FLAGS_XMAC)
-+                      alt_start = 0;
-+              else
-+                      alt_start = 1;
-+              for (i = alt_start; i < niu_num_alt_addr(np); i++) {
-                       err = niu_enable_alt_mac(np, i, 0);
-                       if (err)
-                               printk(KERN_WARNING PFX "%s: Error %d "
-diff -Nurd linux-2.6.24/drivers/net/niu.h linux-2.6.24-oxe810/drivers/net/niu.h
---- linux-2.6.24/drivers/net/niu.h     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/net/niu.h      2008-06-11 17:50:11.000000000 +0200
-@@ -499,7 +499,7 @@
- #define BMAC_ADDR2                    0x00110UL
- #define  BMAC_ADDR2_ADDR2             0x000000000000ffffULL
--#define BMAC_NUM_ALT_ADDR             7
-+#define BMAC_NUM_ALT_ADDR             6
- #define BMAC_ALT_ADDR0(NUM)           (0x00118UL + (NUM)*0x18UL)
- #define  BMAC_ALT_ADDR0_ADDR0         0x000000000000ffffULL
-diff -Nurd linux-2.6.24/drivers/net/pcmcia/smc91c92_cs.c linux-2.6.24-oxe810/drivers/net/pcmcia/smc91c92_cs.c
---- linux-2.6.24/drivers/net/pcmcia/smc91c92_cs.c      2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/net/pcmcia/smc91c92_cs.c       2008-06-11 17:50:04.000000000 +0200
-@@ -559,8 +559,16 @@
-     /* Read the station address from the CIS.  It is stored as the last
-        (fourth) string in the Version 1 Version/ID tuple. */
--    if (link->prod_id[3]) {
--      station_addr = link->prod_id[3];
-+    tuple->DesiredTuple = CISTPL_VERS_1;
-+    if (first_tuple(link, tuple, parse) != CS_SUCCESS) {
-+      rc = -1;
-+      goto free_cfg_mem;
-+    }
-+    /* Ugh -- the EM1144 card has two VERS_1 tuples!?! */
-+    if (next_tuple(link, tuple, parse) != CS_SUCCESS)
-+      first_tuple(link, tuple, parse);
-+    if (parse->version_1.ns > 3) {
-+      station_addr = parse->version_1.str + parse->version_1.ofs[3];
-       if (cvt_ascii_address(dev, station_addr) == 0) {
-               rc = 0;
-               goto free_cfg_mem;
-diff -Nurd linux-2.6.24/drivers/net/sky2.c linux-2.6.24-oxe810/drivers/net/sky2.c
---- linux-2.6.24/drivers/net/sky2.c    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/net/sky2.c     2008-06-11 17:50:11.000000000 +0200
-@@ -621,6 +621,7 @@
-       static const u32 phy_power[] = { PCI_Y2_PHY1_POWD, PCI_Y2_PHY2_POWD };
-       static const u32 coma_mode[] = { PCI_Y2_PHY1_COMA, PCI_Y2_PHY2_COMA };
-+      sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
-       reg1 = sky2_pci_read32(hw, PCI_DEV_REG1);
-       /* Turn on/off phy power saving */
-       if (onoff)
-@@ -632,7 +633,8 @@
-               reg1 |= coma_mode[port];
-       sky2_pci_write32(hw, PCI_DEV_REG1, reg1);
--      reg1 = sky2_pci_read32(hw, PCI_DEV_REG1);
-+      sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
-+      sky2_pci_read32(hw, PCI_DEV_REG1);
-       udelay(100);
- }
-@@ -1412,6 +1414,7 @@
-       imask |= portirq_msk[port];
-       sky2_write32(hw, B0_IMSK, imask);
-+      sky2_set_multicast(dev);
-       return 0;
- err_out:
-@@ -2426,6 +2429,7 @@
-       if (status & (Y2_IS_MST_ERR | Y2_IS_IRQ_STAT)) {
-               u16 pci_err;
-+              sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
-               pci_err = sky2_pci_read16(hw, PCI_STATUS);
-               if (net_ratelimit())
-                       dev_err(&pdev->dev, "PCI hardware error (0x%x)\n",
-@@ -2433,12 +2437,14 @@
-               sky2_pci_write16(hw, PCI_STATUS,
-                                     pci_err | PCI_STATUS_ERROR_BITS);
-+              sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
-       }
-       if (status & Y2_IS_PCI_EXP) {
-               /* PCI-Express uncorrectable Error occurred */
-               u32 err;
-+              sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
-               err = sky2_read32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS);
-               sky2_write32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS,
-                            0xfffffffful);
-@@ -2446,6 +2452,7 @@
-                       dev_err(&pdev->dev, "PCI Express error (0x%x)\n", err);
-               sky2_read32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS);
-+              sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
-       }
-       if (status & Y2_HWE_L1_MASK)
-@@ -2811,6 +2818,7 @@
-       }
-       sky2_power_on(hw);
-+      sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
-       for (i = 0; i < hw->ports; i++) {
-               sky2_write8(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_SET);
-@@ -3533,8 +3541,6 @@
-               err = sky2_up(dev);
-               if (err)
-                       dev_close(dev);
--              else
--                      sky2_set_multicast(dev);
-       }
-       return err;
-@@ -4368,8 +4374,6 @@
-                               dev_close(dev);
-                               goto out;
-                       }
--
--                      sky2_set_multicast(dev);
-               }
-       }
-diff -Nurd linux-2.6.24/drivers/net/via-velocity.c linux-2.6.24-oxe810/drivers/net/via-velocity.c
---- linux-2.6.24/drivers/net/via-velocity.c    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/net/via-velocity.c     2008-06-11 17:50:11.000000000 +0200
+diff -Nurd linux-2.6.24.4/drivers/net/via-velocity.c linux-2.6.24/drivers/net/via-velocity.c
+--- linux-2.6.24.4/drivers/net/via-velocity.c  2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/drivers/net/via-velocity.c    2010-01-14 14:01:15.000000000 +0100
 @@ -72,7 +72,6 @@
  #include <linux/mii.h>
  #include <linux/in.h>
@@ -41631,9 +39407,9 @@ diff -Nurd linux-2.6.24/drivers/net/via-velocity.c linux-2.6.24-oxe810/drivers/n
 -
 -#endif
  #endif
-diff -Nurd linux-2.6.24/drivers/net/via-velocity.h linux-2.6.24-oxe810/drivers/net/via-velocity.h
---- linux-2.6.24/drivers/net/via-velocity.h    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/net/via-velocity.h     2008-06-11 17:50:11.000000000 +0200
+diff -Nurd linux-2.6.24.4/drivers/net/via-velocity.h linux-2.6.24/drivers/net/via-velocity.h
+--- linux-2.6.24.4/drivers/net/via-velocity.h  2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/drivers/net/via-velocity.h    2010-01-14 14:01:15.000000000 +0100
 @@ -25,8 +25,6 @@
  #ifndef VELOCITY_H
  #define VELOCITY_H
@@ -41947,631 +39723,9 @@ diff -Nurd linux-2.6.24/drivers/net/via-velocity.h linux-2.6.24-oxe810/drivers/n
   *    init_flow_control_register      -       set up flow control
   *    @vptr: velocity to configure
   *
-diff -Nurd linux-2.6.24/drivers/net/wireless/b43/dma.c linux-2.6.24-oxe810/drivers/net/wireless/b43/dma.c
---- linux-2.6.24/drivers/net/wireless/b43/dma.c        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/net/wireless/b43/dma.c 2008-06-11 17:49:58.000000000 +0200
-@@ -165,7 +165,7 @@
-       addrhi = (((u64) dmaaddr >> 32) & ~SSB_DMA_TRANSLATION_MASK);
-       addrext = (((u64) dmaaddr >> 32) & SSB_DMA_TRANSLATION_MASK)
-           >> SSB_DMA_TRANSLATION_SHIFT;
--      addrhi |= ssb_dma_translation(ring->dev->dev);
-+      addrhi |= (ssb_dma_translation(ring->dev->dev) << 1);
-       if (slot == ring->nr_slots - 1)
-               ctl0 |= B43_DMA64_DCTL0_DTABLEEND;
-       if (start)
-@@ -426,9 +426,21 @@
- static int alloc_ringmemory(struct b43_dmaring *ring)
- {
-       struct device *dev = ring->dev->dev->dev;
-+      gfp_t flags = GFP_KERNEL;
-+      /* The specs call for 4K buffers for 30- and 32-bit DMA with 4K
-+       * alignment and 8K buffers for 64-bit DMA with 8K alignment. Testing
-+       * has shown that 4K is sufficient for the latter as long as the buffer
-+       * does not cross an 8K boundary.
-+       *
-+       * For unknown reasons - possibly a hardware error - the BCM4311 rev
-+       * 02, which uses 64-bit DMA, needs the ring buffer in very low memory,
-+       * which accounts for the GFP_DMA flag below.
-+       */
-+      if (ring->dma64)
-+              flags |= GFP_DMA;
-       ring->descbase = dma_alloc_coherent(dev, B43_DMA_RINGMEMSIZE,
--                                          &(ring->dmabase), GFP_KERNEL);
-+                                          &(ring->dmabase), flags);
-       if (!ring->descbase) {
-               b43err(ring->dev->wl, "DMA ringmemory allocation failed\n");
-               return -ENOMEM;
-@@ -483,7 +495,7 @@
-       return 0;
- }
--/* Reset the RX DMA channel */
-+/* Reset the TX DMA channel */
- int b43_dmacontroller_tx_reset(struct b43_wldev *dev, u16 mmio_base, int dma64)
- {
-       int i;
-@@ -647,7 +659,7 @@
-                       b43_dma_write(ring, B43_DMA64_TXRINGHI,
-                                     ((ringbase >> 32) &
-                                      ~SSB_DMA_TRANSLATION_MASK)
--                                    | trans);
-+                                    | (trans << 1));
-               } else {
-                       u32 ringbase = (u32) (ring->dmabase);
-@@ -680,8 +692,9 @@
-                       b43_dma_write(ring, B43_DMA64_RXRINGHI,
-                                     ((ringbase >> 32) &
-                                      ~SSB_DMA_TRANSLATION_MASK)
--                                    | trans);
--                      b43_dma_write(ring, B43_DMA64_RXINDEX, 200);
-+                                    | (trans << 1));
-+                      b43_dma_write(ring, B43_DMA64_RXINDEX, ring->nr_slots *
-+                                    sizeof(struct b43_dmadesc64));
-               } else {
-                       u32 ringbase = (u32) (ring->dmabase);
-@@ -695,11 +708,12 @@
-                       b43_dma_write(ring, B43_DMA32_RXRING,
-                                     (ringbase & ~SSB_DMA_TRANSLATION_MASK)
-                                     | trans);
--                      b43_dma_write(ring, B43_DMA32_RXINDEX, 200);
-+                      b43_dma_write(ring, B43_DMA32_RXINDEX, ring->nr_slots *
-+                                    sizeof(struct b43_dmadesc32));
-               }
-       }
--      out:
-+out:
-       return err;
- }
-@@ -1106,7 +1120,7 @@
- {
-       const struct b43_dma_ops *ops = ring->ops;
-       u8 *header;
--      int slot;
-+      int slot, old_top_slot, old_used_slots;
-       int err;
-       struct b43_dmadesc_generic *desc;
-       struct b43_dmadesc_meta *meta;
-@@ -1116,20 +1130,31 @@
- #define SLOTS_PER_PACKET  2
-       B43_WARN_ON(skb_shinfo(skb)->nr_frags);
-+      old_top_slot = ring->current_slot;
-+      old_used_slots = ring->used_slots;
-+
-       /* Get a slot for the header. */
-       slot = request_slot(ring);
-       desc = ops->idx2desc(ring, slot, &meta_hdr);
-       memset(meta_hdr, 0, sizeof(*meta_hdr));
-       header = &(ring->txhdr_cache[slot * sizeof(struct b43_txhdr_fw4)]);
--      b43_generate_txhdr(ring->dev, header,
-+      err = b43_generate_txhdr(ring->dev, header,
-                          skb->data, skb->len, ctl,
-                          generate_cookie(ring, slot));
-+      if (unlikely(err)) {
-+              ring->current_slot = old_top_slot;
-+              ring->used_slots = old_used_slots;
-+              return err;
-+      }
-       meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header,
-                                          sizeof(struct b43_txhdr_fw4), 1);
--      if (dma_mapping_error(meta_hdr->dmaaddr))
-+      if (dma_mapping_error(meta_hdr->dmaaddr)) {
-+              ring->current_slot = old_top_slot;
-+              ring->used_slots = old_used_slots;
-               return -EIO;
-+      }
-       ops->fill_descriptor(ring, desc, meta_hdr->dmaaddr,
-                            sizeof(struct b43_txhdr_fw4), 1, 0, 0);
-@@ -1147,6 +1172,8 @@
-       if (dma_mapping_error(meta->dmaaddr)) {
-               bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA);
-               if (!bounce_skb) {
-+                      ring->current_slot = old_top_slot;
-+                      ring->used_slots = old_used_slots;
-                       err = -ENOMEM;
-                       goto out_unmap_hdr;
-               }
-@@ -1157,6 +1184,8 @@
-               meta->skb = skb;
-               meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
-               if (dma_mapping_error(meta->dmaaddr)) {
-+                      ring->current_slot = old_top_slot;
-+                      ring->used_slots = old_used_slots;
-                       err = -EIO;
-                       goto out_free_bounce;
-               }
-@@ -1219,6 +1248,13 @@
-       B43_WARN_ON(ring->stopped);
-       err = dma_tx_fragment(ring, skb, ctl);
-+      if (unlikely(err == -ENOKEY)) {
-+              /* Drop this packet, as we don't have the encryption key
-+               * anymore and must not transmit it unencrypted. */
-+              dev_kfree_skb_any(skb);
-+              err = 0;
-+              goto out_unlock;
-+      }
-       if (unlikely(err)) {
-               b43err(dev->wl, "DMA tx mapping failure\n");
-               goto out_unlock;
-diff -Nurd linux-2.6.24/drivers/net/wireless/b43/main.c linux-2.6.24-oxe810/drivers/net/wireless/b43/main.c
---- linux-2.6.24/drivers/net/wireless/b43/main.c       2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/net/wireless/b43/main.c        2008-06-11 17:49:58.000000000 +0200
-@@ -101,6 +101,7 @@
-       SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 7),
-       SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 9),
-       SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 10),
-+      SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 13),
-       SSB_DEVTABLE_END
- };
-@@ -1800,6 +1801,18 @@
-               err = -EOPNOTSUPP;
-               goto out;
-       }
-+      if (fwrev > 351) {
-+              b43err(dev->wl, "YOUR FIRMWARE IS TOO NEW. Please downgrade your "
-+                     "firmware.\n");
-+              b43err(dev->wl, "Use this firmware tarball: "
-+                     "http://downloads.openwrt.org/sources/broadcom-wl-4.80.53.0.tar.bz2\n");
-+              b43err(dev->wl, "Use this b43-fwcutter tarball: "
-+                     "http://bu3sch.de/b43/fwcutter/b43-fwcutter-009.tar.bz2\n");
-+              b43err(dev->wl, "Read, understand and _do_ what this message says, please.\n");
-+              b43_write32(dev, B43_MMIO_MACCTL, 0);
-+              err = -EOPNOTSUPP;
-+              goto out;
-+      }
-       b43dbg(dev->wl, "Loading firmware version %u.%u "
-              "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n",
-              fwrev, fwpatch,
-@@ -3067,7 +3080,7 @@
-                       unsupported = 1;
-               break;
-       case B43_PHYTYPE_G:
--              if (phy_rev > 8)
-+              if (phy_rev > 9)
-                       unsupported = 1;
-               break;
-       default:
-@@ -3395,8 +3408,6 @@
-       b43_bluetooth_coext_enable(dev);
-       ssb_bus_powerup(bus, 1);        /* Enable dynamic PCTL */
--      memset(wl->bssid, 0, ETH_ALEN);
--      memset(wl->mac_addr, 0, ETH_ALEN);
-       b43_upload_card_macaddress(dev);
-       b43_security_init(dev);
-       b43_rng_init(wl);
-@@ -3493,6 +3504,13 @@
-       int did_init = 0;
-       int err = 0;
-+      /* Kill all old instance specific information to make sure
-+       * the card won't use it in the short timeframe between start
-+       * and mac80211 reconfiguring it. */
-+      memset(wl->bssid, 0, ETH_ALEN);
-+      memset(wl->mac_addr, 0, ETH_ALEN);
-+      wl->filter_flags = 0;
-+
-       /* First register RFkill.
-        * LEDs that are registered later depend on it. */
-       b43_rfkill_init(dev);
-diff -Nurd linux-2.6.24/drivers/net/wireless/b43/xmit.c linux-2.6.24-oxe810/drivers/net/wireless/b43/xmit.c
---- linux-2.6.24/drivers/net/wireless/b43/xmit.c       2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/net/wireless/b43/xmit.c        2008-06-11 17:49:58.000000000 +0200
-@@ -177,7 +177,7 @@
-       return 0;
- }
--static void generate_txhdr_fw4(struct b43_wldev *dev,
-+static int generate_txhdr_fw4(struct b43_wldev *dev,
-                              struct b43_txhdr_fw4 *txhdr,
-                              const unsigned char *fragment_data,
-                              unsigned int fragment_len,
-@@ -235,7 +235,15 @@
-               B43_WARN_ON(key_idx >= dev->max_nr_keys);
-               key = &(dev->key[key_idx]);
--              B43_WARN_ON(!key->keyconf);
-+
-+              if (unlikely(!key->keyconf)) {
-+                      /* This key is invalid. This might only happen
-+                       * in a short timeframe after machine resume before
-+                       * we were able to reconfigure keys.
-+                       * Drop this packet completely. Do not transmit it
-+                       * unencrypted to avoid leaking information. */
-+                      return -ENOKEY;
-+              }
-               /* Hardware appends ICV. */
-               plcp_fragment_len += txctl->icv_len;
-@@ -352,16 +360,18 @@
-       txhdr->mac_ctl = cpu_to_le32(mac_ctl);
-       txhdr->phy_ctl = cpu_to_le16(phy_ctl);
-       txhdr->extra_ft = extra_ft;
-+
-+      return 0;
- }
--void b43_generate_txhdr(struct b43_wldev *dev,
-+int b43_generate_txhdr(struct b43_wldev *dev,
-                       u8 * txhdr,
-                       const unsigned char *fragment_data,
-                       unsigned int fragment_len,
-                       const struct ieee80211_tx_control *txctl, u16 cookie)
- {
--      generate_txhdr_fw4(dev, (struct b43_txhdr_fw4 *)txhdr,
--                         fragment_data, fragment_len, txctl, cookie);
-+      return generate_txhdr_fw4(dev, (struct b43_txhdr_fw4 *)txhdr,
-+                                fragment_data, fragment_len, txctl, cookie);
- }
- static s8 b43_rssi_postprocess(struct b43_wldev *dev,
-diff -Nurd linux-2.6.24/drivers/net/wireless/b43/xmit.h linux-2.6.24-oxe810/drivers/net/wireless/b43/xmit.h
---- linux-2.6.24/drivers/net/wireless/b43/xmit.h       2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/net/wireless/b43/xmit.h        2008-06-11 17:49:58.000000000 +0200
-@@ -82,7 +82,7 @@
- #define  B43_TX4_PHY_ANT1             0x0100  /* Use antenna 1 */
- #define  B43_TX4_PHY_ANTLAST  0x0300  /* Use last used antenna */
--void b43_generate_txhdr(struct b43_wldev *dev,
-+int b43_generate_txhdr(struct b43_wldev *dev,
-                       u8 * txhdr,
-                       const unsigned char *fragment_data,
-                       unsigned int fragment_len,
-diff -Nurd linux-2.6.24/drivers/net/wireless/b43legacy/dma.c linux-2.6.24-oxe810/drivers/net/wireless/b43legacy/dma.c
---- linux-2.6.24/drivers/net/wireless/b43legacy/dma.c  2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/net/wireless/b43legacy/dma.c   2008-06-11 17:49:57.000000000 +0200
-@@ -1164,7 +1164,7 @@
- {
-       const struct b43legacy_dma_ops *ops = ring->ops;
-       u8 *header;
--      int slot;
-+      int slot, old_top_slot, old_used_slots;
-       int err;
-       struct b43legacy_dmadesc_generic *desc;
-       struct b43legacy_dmadesc_meta *meta;
-@@ -1174,6 +1174,9 @@
- #define SLOTS_PER_PACKET  2
-       B43legacy_WARN_ON(skb_shinfo(skb)->nr_frags != 0);
-+      old_top_slot = ring->current_slot;
-+      old_used_slots = ring->used_slots;
-+
-       /* Get a slot for the header. */
-       slot = request_slot(ring);
-       desc = ops->idx2desc(ring, slot, &meta_hdr);
-@@ -1181,9 +1184,14 @@
-       header = &(ring->txhdr_cache[slot * sizeof(
-                              struct b43legacy_txhdr_fw3)]);
--      b43legacy_generate_txhdr(ring->dev, header,
-+      err = b43legacy_generate_txhdr(ring->dev, header,
-                                skb->data, skb->len, ctl,
-                                generate_cookie(ring, slot));
-+      if (unlikely(err)) {
-+              ring->current_slot = old_top_slot;
-+              ring->used_slots = old_used_slots;
-+              return err;
-+      }
-       meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header,
-                                      sizeof(struct b43legacy_txhdr_fw3), 1);
-@@ -1206,6 +1214,8 @@
-       if (dma_mapping_error(meta->dmaaddr)) {
-               bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA);
-               if (!bounce_skb) {
-+                      ring->current_slot = old_top_slot;
-+                      ring->used_slots = old_used_slots;
-                       err = -ENOMEM;
-                       goto out_unmap_hdr;
-               }
-@@ -1216,6 +1226,8 @@
-               meta->skb = skb;
-               meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
-               if (dma_mapping_error(meta->dmaaddr)) {
-+                      ring->current_slot = old_top_slot;
-+                      ring->used_slots = old_used_slots;
-                       err = -EIO;
-                       goto out_free_bounce;
-               }
-@@ -1282,6 +1294,13 @@
-       B43legacy_BUG_ON(ring->stopped);
-       err = dma_tx_fragment(ring, skb, ctl);
-+      if (unlikely(err == -ENOKEY)) {
-+              /* Drop this packet, as we don't have the encryption key
-+               * anymore and must not transmit it unencrypted. */
-+              dev_kfree_skb_any(skb);
-+              err = 0;
-+              goto out_unlock;
-+      }
-       if (unlikely(err)) {
-               b43legacyerr(dev->wl, "DMA tx mapping failure\n");
-               goto out_unlock;
-diff -Nurd linux-2.6.24/drivers/net/wireless/b43legacy/main.c linux-2.6.24-oxe810/drivers/net/wireless/b43legacy/main.c
---- linux-2.6.24/drivers/net/wireless/b43legacy/main.c 2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/net/wireless/b43legacy/main.c  2008-06-11 17:49:57.000000000 +0200
-@@ -3215,8 +3215,6 @@
-       b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0414, 0x01F4);
-       ssb_bus_powerup(bus, 1); /* Enable dynamic PCTL */
--      memset(wl->bssid, 0, ETH_ALEN);
--      memset(wl->mac_addr, 0, ETH_ALEN);
-       b43legacy_upload_card_macaddress(dev);
-       b43legacy_security_init(dev);
-       b43legacy_rng_init(wl);
-@@ -3311,6 +3309,13 @@
-       int did_init = 0;
-       int err = 0;
-+      /* Kill all old instance specific information to make sure
-+       * the card won't use it in the short timeframe between start
-+       * and mac80211 reconfiguring it. */
-+      memset(wl->bssid, 0, ETH_ALEN);
-+      memset(wl->mac_addr, 0, ETH_ALEN);
-+      wl->filter_flags = 0;
-+
-       mutex_lock(&wl->mutex);
-       if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) {
-diff -Nurd linux-2.6.24/drivers/net/wireless/b43legacy/pio.c linux-2.6.24-oxe810/drivers/net/wireless/b43legacy/pio.c
---- linux-2.6.24/drivers/net/wireless/b43legacy/pio.c  2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/net/wireless/b43legacy/pio.c   2008-06-11 17:49:57.000000000 +0200
-@@ -181,7 +181,7 @@
-       struct b43legacy_txhdr_fw3 txhdr_fw3;
- };
--static void pio_tx_write_fragment(struct b43legacy_pioqueue *queue,
-+static int pio_tx_write_fragment(struct b43legacy_pioqueue *queue,
-                                 struct sk_buff *skb,
-                                 struct b43legacy_pio_txpacket *packet,
-                                 size_t txhdr_size)
-@@ -189,14 +189,17 @@
-       union txhdr_union txhdr_data;
-       u8 *txhdr = NULL;
-       unsigned int octets;
-+      int err;
-       txhdr = (u8 *)(&txhdr_data.txhdr_fw3);
-       B43legacy_WARN_ON(skb_shinfo(skb)->nr_frags != 0);
--      b43legacy_generate_txhdr(queue->dev,
-+      err = b43legacy_generate_txhdr(queue->dev,
-                                txhdr, skb->data, skb->len,
-                                &packet->txstat.control,
-                                generate_cookie(queue, packet));
-+      if (err)
-+              return err;
-       tx_start(queue);
-       octets = skb->len + txhdr_size;
-@@ -204,6 +207,8 @@
-               octets--;
-       tx_data(queue, txhdr, (u8 *)skb->data, octets);
-       tx_complete(queue, skb);
-+
-+      return 0;
- }
- static void free_txpacket(struct b43legacy_pio_txpacket *packet,
-@@ -226,6 +231,7 @@
-       struct b43legacy_pioqueue *queue = packet->queue;
-       struct sk_buff *skb = packet->skb;
-       u16 octets;
-+      int err;
-       octets = (u16)skb->len + sizeof(struct b43legacy_txhdr_fw3);
-       if (queue->tx_devq_size < octets) {
-@@ -247,8 +253,14 @@
-       if (queue->tx_devq_used + octets > queue->tx_devq_size)
-               return -EBUSY;
-       /* Now poke the device. */
--      pio_tx_write_fragment(queue, skb, packet,
-+      err = pio_tx_write_fragment(queue, skb, packet,
-                             sizeof(struct b43legacy_txhdr_fw3));
-+      if (unlikely(err == -ENOKEY)) {
-+              /* Drop this packet, as we don't have the encryption key
-+               * anymore and must not transmit it unencrypted. */
-+              free_txpacket(packet, 1);
-+              return 0;
-+      }
-       /* Account for the packet size.
-        * (We must not overflow the device TX queue)
-@@ -486,6 +498,9 @@
-       queue = parse_cookie(dev, status->cookie, &packet);
-       B43legacy_WARN_ON(!queue);
-+      if (!packet->skb)
-+              return;
-+
-       queue->tx_devq_packets--;
-       queue->tx_devq_used -= (packet->skb->len +
-                               sizeof(struct b43legacy_txhdr_fw3));
-diff -Nurd linux-2.6.24/drivers/net/wireless/b43legacy/xmit.c linux-2.6.24-oxe810/drivers/net/wireless/b43legacy/xmit.c
---- linux-2.6.24/drivers/net/wireless/b43legacy/xmit.c 2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/net/wireless/b43legacy/xmit.c  2008-06-11 17:49:57.000000000 +0200
-@@ -181,7 +181,7 @@
-       return 0;
- }
--static void generate_txhdr_fw3(struct b43legacy_wldev *dev,
-+static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
-                              struct b43legacy_txhdr_fw3 *txhdr,
-                              const unsigned char *fragment_data,
-                              unsigned int fragment_len,
-@@ -252,6 +252,13 @@
-                       iv_len = min((size_t)txctl->iv_len,
-                                    ARRAY_SIZE(txhdr->iv));
-                       memcpy(txhdr->iv, ((u8 *)wlhdr) + wlhdr_len, iv_len);
-+              } else {
-+                      /* This key is invalid. This might only happen
-+                       * in a short timeframe after machine resume before
-+                       * we were able to reconfigure keys.
-+                       * Drop this packet completely. Do not transmit it
-+                       * unencrypted to avoid leaking information. */
-+                      return -ENOKEY;
-               }
-       }
-       b43legacy_generate_plcp_hdr((struct b43legacy_plcp_hdr4 *)
-@@ -344,16 +351,18 @@
-       /* Apply the bitfields */
-       txhdr->mac_ctl = cpu_to_le32(mac_ctl);
-       txhdr->phy_ctl = cpu_to_le16(phy_ctl);
-+
-+      return 0;
- }
--void b43legacy_generate_txhdr(struct b43legacy_wldev *dev,
-+int b43legacy_generate_txhdr(struct b43legacy_wldev *dev,
-                             u8 *txhdr,
-                             const unsigned char *fragment_data,
-                             unsigned int fragment_len,
-                             const struct ieee80211_tx_control *txctl,
-                             u16 cookie)
- {
--      generate_txhdr_fw3(dev, (struct b43legacy_txhdr_fw3 *)txhdr,
-+      return generate_txhdr_fw3(dev, (struct b43legacy_txhdr_fw3 *)txhdr,
-                          fragment_data, fragment_len,
-                          txctl, cookie);
- }
-diff -Nurd linux-2.6.24/drivers/net/wireless/b43legacy/xmit.h linux-2.6.24-oxe810/drivers/net/wireless/b43legacy/xmit.h
---- linux-2.6.24/drivers/net/wireless/b43legacy/xmit.h 2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/net/wireless/b43legacy/xmit.h  2008-06-11 17:49:57.000000000 +0200
-@@ -76,7 +76,7 @@
--void b43legacy_generate_txhdr(struct b43legacy_wldev *dev,
-+int b43legacy_generate_txhdr(struct b43legacy_wldev *dev,
-                             u8 *txhdr,
-                             const unsigned char *fragment_data,
-                             unsigned int fragment_len,
-diff -Nurd linux-2.6.24/drivers/pci/hotplug/fakephp.c linux-2.6.24-oxe810/drivers/pci/hotplug/fakephp.c
---- linux-2.6.24/drivers/pci/hotplug/fakephp.c 2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/pci/hotplug/fakephp.c  2008-06-11 17:49:28.000000000 +0200
-@@ -39,6 +39,7 @@
- #include <linux/init.h>
- #include <linux/string.h>
- #include <linux/slab.h>
-+#include <linux/workqueue.h>
- #include "../pci.h"
- #if !defined(MODULE)
-@@ -63,10 +64,16 @@
-       struct list_head node;
-       struct hotplug_slot *slot;
-       struct pci_dev *dev;
-+      struct work_struct remove_work;
-+      unsigned long removed;
- };
- static int debug;
- static LIST_HEAD(slot_list);
-+static struct workqueue_struct *dummyphp_wq;
-+
-+static void pci_rescan_worker(struct work_struct *work);
-+static DECLARE_WORK(pci_rescan_work, pci_rescan_worker);
- static int enable_slot (struct hotplug_slot *slot);
- static int disable_slot (struct hotplug_slot *slot);
-@@ -109,7 +116,7 @@
-       slot->name = &dev->dev.bus_id[0];
-       dbg("slot->name = %s\n", slot->name);
--      dslot = kmalloc(sizeof(struct dummy_slot), GFP_KERNEL);
-+      dslot = kzalloc(sizeof(struct dummy_slot), GFP_KERNEL);
-       if (!dslot)
-               goto error_info;
-@@ -164,6 +171,14 @@
-               err("Problem unregistering a slot %s\n", dslot->slot->name);
- }
-+/* called from the single-threaded workqueue handler to remove a slot */
-+static void remove_slot_worker(struct work_struct *work)
-+{
-+      struct dummy_slot *dslot =
-+              container_of(work, struct dummy_slot, remove_work);
-+      remove_slot(dslot);
-+}
-+
- /**
-  * pci_rescan_slot - Rescan slot
-  * @temp: Device template. Should be set: bus and devfn.
-@@ -267,11 +282,17 @@
-       pci_rescan_buses(&pci_root_buses);
- }
-+/* called from the single-threaded workqueue handler to rescan all pci buses */
-+static void pci_rescan_worker(struct work_struct *work)
-+{
-+      pci_rescan();
-+}
- static int enable_slot(struct hotplug_slot *hotplug_slot)
- {
-       /* mis-use enable_slot for rescanning of the pci bus */
--      pci_rescan();
-+      cancel_work_sync(&pci_rescan_work);
-+      queue_work(dummyphp_wq, &pci_rescan_work);
-       return -ENODEV;
- }
-@@ -306,6 +327,10 @@
-               err("Can't remove PCI devices with other PCI devices behind it yet.\n");
-               return -ENODEV;
-       }
-+      if (test_and_set_bit(0, &dslot->removed)) {
-+              dbg("Slot already scheduled for removal\n");
-+              return -ENODEV;
-+      }
-       /* search for subfunctions and disable them first */
-       if (!(dslot->dev->devfn & 7)) {
-               for (func = 1; func < 8; func++) {
-@@ -328,8 +353,9 @@
-       /* remove the device from the pci core */
-       pci_remove_bus_device(dslot->dev);
--      /* blow away this sysfs entry and other parts. */
--      remove_slot(dslot);
-+      /* queue work item to blow away this sysfs entry and other parts. */
-+      INIT_WORK(&dslot->remove_work, remove_slot_worker);
-+      queue_work(dummyphp_wq, &dslot->remove_work);
-       return 0;
- }
-@@ -340,6 +366,7 @@
-       struct list_head *next;
-       struct dummy_slot *dslot;
-+      destroy_workqueue(dummyphp_wq);
-       list_for_each_safe (tmp, next, &slot_list) {
-               dslot = list_entry (tmp, struct dummy_slot, node);
-               remove_slot(dslot);
-@@ -351,6 +378,10 @@
- {
-       info(DRIVER_DESC "\n");
-+      dummyphp_wq = create_singlethread_workqueue(MY_NAME);
-+      if (!dummyphp_wq)
-+              return -ENOMEM;
-+
-       return pci_scan_buses();
- }
-diff -Nurd linux-2.6.24/drivers/pci/probe.c linux-2.6.24-oxe810/drivers/pci/probe.c
---- linux-2.6.24/drivers/pci/probe.c   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/pci/probe.c    2008-06-11 17:49:28.000000000 +0200
+diff -Nurd linux-2.6.24.4/drivers/pci/probe.c linux-2.6.24/drivers/pci/probe.c
+--- linux-2.6.24.4/drivers/pci/probe.c 2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/drivers/pci/probe.c   2010-01-14 14:01:15.000000000 +0100
 @@ -991,8 +991,18 @@
        for (func = 0; func < 8; func++, devfn++) {
                struct pci_dev *dev;
@@ -42593,9 +39747,9 @@ diff -Nurd linux-2.6.24/drivers/pci/probe.c linux-2.6.24-oxe810/drivers/pci/prob
                        nr++;
  
                        /*
-diff -Nurd linux-2.6.24/drivers/rtc/rtc-ds1307.c linux-2.6.24-oxe810/drivers/rtc/rtc-ds1307.c
---- linux-2.6.24/drivers/rtc/rtc-ds1307.c      2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/rtc/rtc-ds1307.c       2008-06-11 17:49:41.000000000 +0200
+diff -Nurd linux-2.6.24.4/drivers/rtc/rtc-ds1307.c linux-2.6.24/drivers/rtc/rtc-ds1307.c
+--- linux-2.6.24.4/drivers/rtc/rtc-ds1307.c    2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/drivers/rtc/rtc-ds1307.c      2010-01-14 14:01:15.000000000 +0100
 @@ -17,7 +17,7 @@
  #include <linux/rtc.h>
  #include <linux/bcd.h>
@@ -42621,23 +39775,9 @@ diff -Nurd linux-2.6.24/drivers/rtc/rtc-ds1307.c linux-2.6.24-oxe810/drivers/rtc
  
        tmp = ds1307->regs[DS1307_REG_HOUR];
        switch (ds1307->type) {
-diff -Nurd linux-2.6.24/drivers/s390/char/defkeymap.c linux-2.6.24-oxe810/drivers/s390/char/defkeymap.c
---- linux-2.6.24/drivers/s390/char/defkeymap.c 2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/s390/char/defkeymap.c  2008-06-11 17:49:17.000000000 +0200
-@@ -151,8 +151,8 @@
- };
- struct kbdiacruc accent_table[MAX_DIACR] = {
--      {'^', 'c', '\003'},     {'^', 'd', '\004'},
--      {'^', 'z', '\032'},     {'^', '\012', '\000'},
-+      {'^', 'c', 0003},       {'^', 'd', 0004},
-+      {'^', 'z', 0032},       {'^', 0012, 0000},
- };
- unsigned int accent_table_size = 4;
-diff -Nurd linux-2.6.24/drivers/scsi/Kconfig linux-2.6.24-oxe810/drivers/scsi/Kconfig
---- linux-2.6.24/drivers/scsi/Kconfig  2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/scsi/Kconfig   2008-06-11 17:50:29.000000000 +0200
+diff -Nurd linux-2.6.24.4/drivers/scsi/Kconfig linux-2.6.24/drivers/scsi/Kconfig
+--- linux-2.6.24.4/drivers/scsi/Kconfig        2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/drivers/scsi/Kconfig  2010-01-14 14:01:15.000000000 +0100
 @@ -556,6 +556,15 @@
          To compile this driver as a module, choose M here: the
          module will be called arcmsr (modprobe arcmsr).
@@ -42654,612 +39794,9 @@ diff -Nurd linux-2.6.24/drivers/scsi/Kconfig linux-2.6.24-oxe810/drivers/scsi/Kc
  config SCSI_ARCMSR_AER
        bool "Enable PCI Error Recovery Capability in Areca Driver(ARCMSR)"
        depends on SCSI_ARCMSR && PCIEAER
-diff -Nurd linux-2.6.24/drivers/scsi/advansys.c linux-2.6.24-oxe810/drivers/scsi/advansys.c
---- linux-2.6.24/drivers/scsi/advansys.c       2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/scsi/advansys.c        2008-06-11 17:50:28.000000000 +0200
-@@ -566,7 +566,7 @@
-       ASC_SCSI_BIT_ID_TYPE unit_not_ready;
-       ASC_SCSI_BIT_ID_TYPE queue_full_or_busy;
-       ASC_SCSI_BIT_ID_TYPE start_motor;
--      uchar overrun_buf[ASC_OVERRUN_BSIZE] __aligned(8);
-+      uchar *overrun_buf;
-       dma_addr_t overrun_dma;
-       uchar scsi_reset_wait;
-       uchar chip_no;
-@@ -6439,7 +6439,7 @@
-                       i += 2;
-                       len += 2;
-               } else {
--                      unsigned char off = buf[i] * 2;
-+                      unsigned int off = buf[i] * 2;
-                       unsigned short word = (buf[off + 1] << 8) | buf[off];
-                       AdvWriteWordAutoIncLram(iop_base, word);
-                       len += 2;
-@@ -13833,6 +13833,12 @@
-        */
-       if (ASC_NARROW_BOARD(boardp)) {
-               ASC_DBG(2, "AscInitAsc1000Driver()\n");
-+
-+              asc_dvc_varp->overrun_buf = kzalloc(ASC_OVERRUN_BSIZE, GFP_KERNEL);
-+              if (!asc_dvc_varp->overrun_buf) {
-+                      ret = -ENOMEM;
-+                      goto err_free_wide_mem;
-+              }
-               warn_code = AscInitAsc1000Driver(asc_dvc_varp);
-               if (warn_code || asc_dvc_varp->err_code) {
-@@ -13840,8 +13846,10 @@
-                                       "warn 0x%x, error 0x%x\n",
-                                       asc_dvc_varp->init_state, warn_code,
-                                       asc_dvc_varp->err_code);
--                      if (asc_dvc_varp->err_code)
-+                      if (asc_dvc_varp->err_code) {
-                               ret = -ENODEV;
-+                              kfree(asc_dvc_varp->overrun_buf);
-+                      }
-               }
-       } else {
-               if (advansys_wide_init_chip(shost))
-@@ -13894,6 +13902,7 @@
-               dma_unmap_single(board->dev,
-                                       board->dvc_var.asc_dvc_var.overrun_dma,
-                                       ASC_OVERRUN_BSIZE, DMA_FROM_DEVICE);
-+              kfree(board->dvc_var.asc_dvc_var.overrun_buf);
-       } else {
-               iounmap(board->ioremap_addr);
-               advansys_wide_free_mem(board);
-diff -Nurd linux-2.6.24/drivers/scsi/aic94xx/aic94xx_scb.c linux-2.6.24-oxe810/drivers/scsi/aic94xx/aic94xx_scb.c
---- linux-2.6.24/drivers/scsi/aic94xx/aic94xx_scb.c    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/scsi/aic94xx/aic94xx_scb.c     2008-06-11 17:50:27.000000000 +0200
-@@ -458,13 +458,19 @@
-               tc_abort = le16_to_cpu(tc_abort);
-               list_for_each_entry_safe(a, b, &asd_ha->seq.pend_q, list) {
--                      struct sas_task *task = ascb->uldd_task;
-+                      struct sas_task *task = a->uldd_task;
--                      if (task && a->tc_index == tc_abort) {
-+                      if (a->tc_index != tc_abort)
-+                              continue;
-+
-+                      if (task) {
-                               failed_dev = task->dev;
-                               sas_task_abort(task);
--                              break;
-+                      } else {
-+                              ASD_DPRINTK("R_T_A for non TASK scb 0x%x\n",
-+                                          a->scb->header.opcode);
-                       }
-+                      break;
-               }
-               if (!failed_dev) {
-@@ -478,7 +484,7 @@
-                * that the EH will wake up and do something.
-                */
-               list_for_each_entry_safe(a, b, &asd_ha->seq.pend_q, list) {
--                      struct sas_task *task = ascb->uldd_task;
-+                      struct sas_task *task = a->uldd_task;
-                       if (task &&
-                           task->dev == failed_dev &&
-diff -Nurd linux-2.6.24/drivers/scsi/arcmsr/arcmsr_hba.c linux-2.6.24-oxe810/drivers/scsi/arcmsr/arcmsr_hba.c
---- linux-2.6.24/drivers/scsi/arcmsr/arcmsr_hba.c      2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/scsi/arcmsr/arcmsr_hba.c       2008-06-11 17:50:28.000000000 +0200
-@@ -1380,17 +1380,16 @@
-       switch(controlcode) {
-       case ARCMSR_MESSAGE_READ_RQBUFFER: {
--              unsigned long *ver_addr;
--              dma_addr_t buf_handle;
-+              unsigned char *ver_addr;
-               uint8_t *pQbuffer, *ptmpQbuffer;
-               int32_t allxfer_len = 0;
--              ver_addr = pci_alloc_consistent(acb->pdev, 1032, &buf_handle);
-+              ver_addr = kmalloc(1032, GFP_ATOMIC);
-               if (!ver_addr) {
-                       retvalue = ARCMSR_MESSAGE_FAIL;
-                       goto message_out;
-               }
--              ptmpQbuffer = (uint8_t *) ver_addr;
-+              ptmpQbuffer = ver_addr;
-               while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex)
-                       && (allxfer_len < 1031)) {
-                       pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex];
-@@ -1419,25 +1418,24 @@
-                       }
-                       arcmsr_iop_message_read(acb);
-               }
--              memcpy(pcmdmessagefld->messagedatabuffer, (uint8_t *)ver_addr, allxfer_len);
-+              memcpy(pcmdmessagefld->messagedatabuffer, ver_addr, allxfer_len);
-               pcmdmessagefld->cmdmessage.Length = allxfer_len;
-               pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
--              pci_free_consistent(acb->pdev, 1032, ver_addr, buf_handle);
-+              kfree(ver_addr);
-               }
-               break;
-       case ARCMSR_MESSAGE_WRITE_WQBUFFER: {
--              unsigned long *ver_addr;
--              dma_addr_t buf_handle;
-+              unsigned char *ver_addr;
-               int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex;
-               uint8_t *pQbuffer, *ptmpuserbuffer;
--              ver_addr = pci_alloc_consistent(acb->pdev, 1032, &buf_handle);
-+              ver_addr = kmalloc(1032, GFP_ATOMIC);
-               if (!ver_addr) {
-                       retvalue = ARCMSR_MESSAGE_FAIL;
-                       goto message_out;
-               }
--              ptmpuserbuffer = (uint8_t *)ver_addr;
-+              ptmpuserbuffer = ver_addr;
-               user_len = pcmdmessagefld->cmdmessage.Length;
-               memcpy(ptmpuserbuffer, pcmdmessagefld->messagedatabuffer, user_len);
-               wqbuf_lastindex = acb->wqbuf_lastindex;
-@@ -1483,7 +1481,7 @@
-                               retvalue = ARCMSR_MESSAGE_FAIL;
-                       }
-                       }
--                      pci_free_consistent(acb->pdev, 1032, ver_addr, buf_handle);
-+                      kfree(ver_addr);
-               }
-               break;
-diff -Nurd linux-2.6.24/drivers/scsi/gdth.c linux-2.6.24-oxe810/drivers/scsi/gdth.c
---- linux-2.6.24/drivers/scsi/gdth.c   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/scsi/gdth.c    2008-06-11 17:50:29.000000000 +0200
-@@ -160,7 +160,7 @@
- static void gdth_clear_events(void);
- static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp,
--                                    char *buffer, ushort count, int to_buffer);
-+                                    char *buffer, ushort count);
- static int gdth_internal_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp);
- static int gdth_fill_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, ushort hdrive);
-@@ -183,7 +183,6 @@
-                       unsigned int cmd, unsigned long arg);
- static void gdth_flush(gdth_ha_str *ha);
--static int gdth_halt(struct notifier_block *nb, ulong event, void *buf);
- static int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *));
- static int __gdth_queuecommand(gdth_ha_str *ha, struct scsi_cmnd *scp,
-                               struct gdth_cmndinfo *cmndinfo);
-@@ -418,12 +417,6 @@
- #include "gdth_proc.h"
- #include "gdth_proc.c"
--/* notifier block to get a notify on system shutdown/halt/reboot */
--static struct notifier_block gdth_notifier = {
--    gdth_halt, NULL, 0
--};
--static int notifier_disabled = 0;
--
- static gdth_ha_str *gdth_find_ha(int hanum)
- {
-       gdth_ha_str *ha;
-@@ -446,8 +439,8 @@
-       for (i=0; i<GDTH_MAXCMDS; ++i) {
-               if (ha->cmndinfo[i].index == 0) {
-                       priv = &ha->cmndinfo[i];
--                      priv->index = i+1;
-                       memset(priv, 0, sizeof(*priv));
-+                      priv->index = i+1;
-                       break;
-               }
-       }
-@@ -494,7 +487,6 @@
-     gdth_ha_str *ha = shost_priv(sdev->host);
-     Scsi_Cmnd *scp;
-     struct gdth_cmndinfo cmndinfo;
--    struct scatterlist one_sg;
-     DECLARE_COMPLETION_ONSTACK(wait);
-     int rval;
-@@ -508,13 +500,10 @@
-     /* use request field to save the ptr. to completion struct. */
-     scp->request = (struct request *)&wait;
-     scp->timeout_per_command = timeout*HZ;
--    sg_init_one(&one_sg, gdtcmd, sizeof(*gdtcmd));
--    gdth_set_sglist(scp, &one_sg);
--    gdth_set_sg_count(scp, 1);
--    gdth_set_bufflen(scp, sizeof(*gdtcmd));
-     scp->cmd_len = 12;
-     memcpy(scp->cmnd, cmnd, 12);
-     cmndinfo.priority = IOCTL_PRI;
-+    cmndinfo.internal_cmd_str = gdtcmd;
-     cmndinfo.internal_command = 1;
-     TRACE(("__gdth_execute() cmd 0x%x\n", scp->cmnd[0]));
-@@ -2355,7 +2344,7 @@
-  * buffers, kmap_atomic() as needed.
-  */
- static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp,
--                                    char *buffer, ushort count, int to_buffer)
-+                                    char *buffer, ushort count)
- {
-     ushort cpcount,i, max_sg = gdth_sg_count(scp);
-     ushort cpsum,cpnow;
-@@ -2381,10 +2370,7 @@
-             }
-             local_irq_save(flags);
-             address = kmap_atomic(sg_page(sl), KM_BIO_SRC_IRQ) + sl->offset;
--            if (to_buffer)
--                memcpy(buffer, address, cpnow);
--            else
--                memcpy(address, buffer, cpnow);
-+            memcpy(address, buffer, cpnow);
-             flush_dcache_page(sg_page(sl));
-             kunmap_atomic(address, KM_BIO_SRC_IRQ);
-             local_irq_restore(flags);
-@@ -2438,7 +2424,7 @@
-         strcpy(inq.vendor,ha->oem_name);
-         sprintf(inq.product,"Host Drive  #%02d",t);
-         strcpy(inq.revision,"   ");
--        gdth_copy_internal_data(ha, scp, (char*)&inq, sizeof(gdth_inq_data), 0);
-+        gdth_copy_internal_data(ha, scp, (char*)&inq, sizeof(gdth_inq_data));
-         break;
-       case REQUEST_SENSE:
-@@ -2448,7 +2434,7 @@
-         sd.key       = NO_SENSE;
-         sd.info      = 0;
-         sd.add_length= 0;
--        gdth_copy_internal_data(ha, scp, (char*)&sd, sizeof(gdth_sense_data), 0);
-+        gdth_copy_internal_data(ha, scp, (char*)&sd, sizeof(gdth_sense_data));
-         break;
-       case MODE_SENSE:
-@@ -2460,7 +2446,7 @@
-         mpd.bd.block_length[0] = (SECTOR_SIZE & 0x00ff0000) >> 16;
-         mpd.bd.block_length[1] = (SECTOR_SIZE & 0x0000ff00) >> 8;
-         mpd.bd.block_length[2] = (SECTOR_SIZE & 0x000000ff);
--        gdth_copy_internal_data(ha, scp, (char*)&mpd, sizeof(gdth_modep_data), 0);
-+        gdth_copy_internal_data(ha, scp, (char*)&mpd, sizeof(gdth_modep_data));
-         break;
-       case READ_CAPACITY:
-@@ -2470,7 +2456,7 @@
-         else
-             rdc.last_block_no = cpu_to_be32(ha->hdr[t].size-1);
-         rdc.block_length  = cpu_to_be32(SECTOR_SIZE);
--        gdth_copy_internal_data(ha, scp, (char*)&rdc, sizeof(gdth_rdcap_data), 0);
-+        gdth_copy_internal_data(ha, scp, (char*)&rdc, sizeof(gdth_rdcap_data));
-         break;
-       case SERVICE_ACTION_IN:
-@@ -2482,7 +2468,7 @@
-             rdc16.last_block_no = cpu_to_be64(ha->hdr[t].size-1);
-             rdc16.block_length  = cpu_to_be32(SECTOR_SIZE);
-             gdth_copy_internal_data(ha, scp, (char*)&rdc16,
--                                                 sizeof(gdth_rdcap16_data), 0);
-+                                                 sizeof(gdth_rdcap16_data));
-         } else { 
-             scp->result = DID_ABORT << 16;
-         }
-@@ -2852,6 +2838,7 @@
- static int gdth_special_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp)
- {
-     register gdth_cmd_str *cmdp;
-+    struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp);
-     int cmd_index;
-     cmdp= ha->pccb;
-@@ -2860,7 +2847,7 @@
-     if (ha->type==GDT_EISA && ha->cmd_cnt>0) 
-         return 0;
--    gdth_copy_internal_data(ha, scp, (char *)cmdp, sizeof(gdth_cmd_str), 1);
-+    *cmdp = *cmndinfo->internal_cmd_str;
-     cmdp->RequestBuffer = scp;
-     /* search free command index */
-@@ -3793,6 +3780,8 @@
-     gdth_ha_str *ha;
-     ulong flags;
-+    BUG_ON(list_empty(&gdth_instances));
-+
-     ha = list_first_entry(&gdth_instances, gdth_ha_str, list);
-     spin_lock_irqsave(&ha->smp_lock, flags);
-@@ -4668,45 +4657,6 @@
-     }
- }
--/* shutdown routine */
--static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
--{
--    gdth_ha_str *ha;
--#ifndef __alpha__
--    gdth_cmd_str    gdtcmd;
--    char            cmnd[MAX_COMMAND_SIZE];   
--#endif
--
--    if (notifier_disabled)
--        return NOTIFY_OK;
--
--    TRACE2(("gdth_halt() event %d\n",(int)event));
--    if (event != SYS_RESTART && event != SYS_HALT && event != SYS_POWER_OFF)
--        return NOTIFY_DONE;
--
--    notifier_disabled = 1;
--    printk("GDT-HA: Flushing all host drives .. ");
--    list_for_each_entry(ha, &gdth_instances, list) {
--        gdth_flush(ha);
--
--#ifndef __alpha__
--        /* controller reset */
--        memset(cmnd, 0xff, MAX_COMMAND_SIZE);
--        gdtcmd.BoardNode = LOCALBOARD;
--        gdtcmd.Service = CACHESERVICE;
--        gdtcmd.OpCode = GDT_RESET;
--        TRACE2(("gdth_halt(): reset controller %d\n", ha->hanum));
--        gdth_execute(ha->shost, &gdtcmd, cmnd, 10, NULL);
--#endif
--    }
--    printk("Done.\n");
--
--#ifdef GDTH_STATISTICS
--    del_timer(&gdth_timer);
--#endif
--    return NOTIFY_OK;
--}
--
- /* configure lun */
- static int gdth_slave_configure(struct scsi_device *sdev)
- {
-@@ -4838,6 +4788,9 @@
-       if (error)
-               goto out_free_coal_stat;
-       list_add_tail(&ha->list, &gdth_instances);
-+
-+      scsi_scan_host(shp);
-+
-       return 0;
-  out_free_coal_stat:
-@@ -4965,6 +4918,9 @@
-       if (error)
-               goto out_free_coal_stat;
-       list_add_tail(&ha->list, &gdth_instances);
-+
-+      scsi_scan_host(shp);
-+
-       return 0;
-  out_free_ccb_phys:
-@@ -5102,6 +5058,9 @@
-       if (error)
-               goto out_free_coal_stat;
-       list_add_tail(&ha->list, &gdth_instances);
-+
-+      scsi_scan_host(shp);
-+
-       return 0;
-  out_free_coal_stat:
-@@ -5132,13 +5091,13 @@
-       scsi_remove_host(shp);
-+      gdth_flush(ha);
-+
-       if (ha->sdev) {
-               scsi_free_host_dev(ha->sdev);
-               ha->sdev = NULL;
-       }
--      gdth_flush(ha);
--
-       if (shp->irq)
-               free_irq(shp->irq,ha);
-@@ -5164,6 +5123,24 @@
-       scsi_host_put(shp);
- }
-+static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
-+{
-+      gdth_ha_str *ha;
-+
-+      TRACE2(("gdth_halt() event %d\n", (int)event));
-+      if (event != SYS_RESTART && event != SYS_HALT && event != SYS_POWER_OFF)
-+              return NOTIFY_DONE;
-+
-+      list_for_each_entry(ha, &gdth_instances, list)
-+              gdth_flush(ha);
-+
-+      return NOTIFY_OK;
-+}
-+
-+static struct notifier_block gdth_notifier = {
-+    gdth_halt, NULL, 0
-+};
-+
- static int __init gdth_init(void)
- {
-       if (disable) {
-@@ -5226,7 +5203,6 @@
-       add_timer(&gdth_timer);
- #endif
-       major = register_chrdev(0,"gdth", &gdth_fops);
--      notifier_disabled = 0;
-       register_reboot_notifier(&gdth_notifier);
-       gdth_polling = FALSE;
-       return 0;
-@@ -5236,14 +5212,15 @@
- {
-       gdth_ha_str *ha;
--      list_for_each_entry(ha, &gdth_instances, list)
--              gdth_remove_one(ha);
-+      unregister_chrdev(major, "gdth");
-+      unregister_reboot_notifier(&gdth_notifier);
- #ifdef GDTH_STATISTICS
--      del_timer(&gdth_timer);
-+      del_timer_sync(&gdth_timer);
- #endif
--      unregister_chrdev(major,"gdth");
--      unregister_reboot_notifier(&gdth_notifier);
-+
-+      list_for_each_entry(ha, &gdth_instances, list)
-+              gdth_remove_one(ha);
- }
- module_init(gdth_init);
-diff -Nurd linux-2.6.24/drivers/scsi/gdth.h linux-2.6.24-oxe810/drivers/scsi/gdth.h
---- linux-2.6.24/drivers/scsi/gdth.h   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/scsi/gdth.h    2008-06-11 17:50:29.000000000 +0200
-@@ -915,6 +915,7 @@
-     struct gdth_cmndinfo {                      /* per-command private info */
-         int index;
-         int internal_command;                   /* don't call scsi_done */
-+        gdth_cmd_str *internal_cmd_str;         /* crier for internal messages*/
-         dma_addr_t sense_paddr;                 /* sense dma-addr */
-         unchar priority;
-         int timeout;
-diff -Nurd linux-2.6.24/drivers/scsi/gdth_proc.c linux-2.6.24-oxe810/drivers/scsi/gdth_proc.c
---- linux-2.6.24/drivers/scsi/gdth_proc.c      2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/scsi/gdth_proc.c       2008-06-11 17:50:29.000000000 +0200
-@@ -694,15 +694,13 @@
- {
-     ulong flags;
--    spin_lock_irqsave(&ha->smp_lock, flags);
--
-     if (buf == ha->pscratch) {
-+      spin_lock_irqsave(&ha->smp_lock, flags);
-         ha->scratch_busy = FALSE;
-+      spin_unlock_irqrestore(&ha->smp_lock, flags);
-     } else {
-         pci_free_consistent(ha->pdev, size, buf, paddr);
-     }
--
--    spin_unlock_irqrestore(&ha->smp_lock, flags);
- }
- #ifdef GDTH_IOCTL_PROC
-diff -Nurd linux-2.6.24/drivers/scsi/ips.c linux-2.6.24-oxe810/drivers/scsi/ips.c
---- linux-2.6.24/drivers/scsi/ips.c    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/scsi/ips.c     2008-06-11 17:50:29.000000000 +0200
-@@ -1580,7 +1580,7 @@
-       METHOD_TRACE("ips_make_passthru", 1);
-         scsi_for_each_sg(SC, sg, scsi_sg_count(SC), i)
--                length += sg[i].length;
-+              length += sg->length;
-       if (length < sizeof (ips_passthru_t)) {
-               /* wrong size */
-@@ -6842,13 +6842,10 @@
-       if (request_irq(ha->irq, do_ipsintr, IRQF_SHARED, ips_name, ha)) {
-               IPS_PRINTK(KERN_WARNING, ha->pcidev,
-                          "Unable to install interrupt handler\n");
--              scsi_host_put(sh);
--              return -1;
-+              goto err_out_sh;
-       }
-       kfree(oldha);
--      ips_sh[index] = sh;
--      ips_ha[index] = ha;
-       /* Store away needed values for later use */
-       sh->io_port = ha->io_addr;
-@@ -6867,10 +6864,21 @@
-       sh->max_channel = ha->nbus - 1;
-       sh->can_queue = ha->max_cmds - 1;
--      scsi_add_host(sh, NULL);
-+      if (scsi_add_host(sh, &ha->pcidev->dev))
-+              goto err_out;
-+
-+      ips_sh[index] = sh;
-+      ips_ha[index] = ha;
-+
-       scsi_scan_host(sh);
-       return 0;
-+
-+err_out:
-+      free_irq(ha->pcidev->irq, ha);
-+err_out_sh:
-+      scsi_host_put(sh);
-+      return -1;
- }
- /*---------------------------------------------------------------------------*/
-diff -Nurd linux-2.6.24/drivers/scsi/scsi_lib.c linux-2.6.24-oxe810/drivers/scsi/scsi_lib.c
---- linux-2.6.24/drivers/scsi/scsi_lib.c       2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/scsi/scsi_lib.c        2008-06-11 17:50:29.000000000 +0200
-@@ -298,7 +298,6 @@
-               page = sg_page(sg);
-               off = sg->offset;
-               len = sg->length;
--              data_len += len;
-               while (len > 0 && data_len > 0) {
-                       /*
-diff -Nurd linux-2.6.24/drivers/scsi/sd.c linux-2.6.24-oxe810/drivers/scsi/sd.c
---- linux-2.6.24/drivers/scsi/sd.c     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/scsi/sd.c      2008-06-11 17:50:29.000000000 +0200
-@@ -907,6 +907,7 @@
-       unsigned int xfer_size = SCpnt->request_bufflen;
-       unsigned int good_bytes = result ? 0 : xfer_size;
-       u64 start_lba = SCpnt->request->sector;
-+      u64 end_lba = SCpnt->request->sector + (xfer_size / 512);
-       u64 bad_lba;
-       struct scsi_sense_hdr sshdr;
-       int sense_valid = 0;
-@@ -945,26 +946,23 @@
-                       goto out;
-               if (xfer_size <= SCpnt->device->sector_size)
-                       goto out;
--              switch (SCpnt->device->sector_size) {
--              case 256:
-+              if (SCpnt->device->sector_size < 512) {
-+                      /* only legitimate sector_size here is 256 */
-                       start_lba <<= 1;
--                      break;
--              case 512:
--                      break;
--              case 1024:
--                      start_lba >>= 1;
--                      break;
--              case 2048:
--                      start_lba >>= 2;
--                      break;
--              case 4096:
--                      start_lba >>= 3;
--                      break;
--              default:
--                      /* Print something here with limiting frequency. */
--                      goto out;
--                      break;
-+                      end_lba <<= 1;
-+              } else {
-+                      /* be careful ... don't want any overflows */
-+                      u64 factor = SCpnt->device->sector_size / 512;
-+                      do_div(start_lba, factor);
-+                      do_div(end_lba, factor);
-               }
-+
-+              if (bad_lba < start_lba  || bad_lba >= end_lba)
-+                      /* the bad lba was reported incorrectly, we have
-+                       * no idea where the error is
-+                       */
-+                      goto out;
-+
-               /* This computation should always be done in terms of
-                * the resolution of the device's medium.
-                */
-diff -Nurd linux-2.6.24/drivers/serial/8250.c linux-2.6.24-oxe810/drivers/serial/8250.c
---- linux-2.6.24/drivers/serial/8250.c 2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/serial/8250.c  2008-06-11 17:48:56.000000000 +0200
+diff -Nurd linux-2.6.24.4/drivers/serial/8250.c linux-2.6.24/drivers/serial/8250.c
+--- linux-2.6.24.4/drivers/serial/8250.c       2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/drivers/serial/8250.c 2010-01-14 14:01:15.000000000 +0100
 @@ -2153,7 +2153,37 @@
                serial_outp(up, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
        }
@@ -43312,154 +39849,9 @@ diff -Nurd linux-2.6.24/drivers/serial/8250.c linux-2.6.24-oxe810/drivers/serial
        int bits = 8;
        int parity = 'n';
        int flow = 'n';
-diff -Nurd linux-2.6.24/drivers/spi/atmel_spi.c linux-2.6.24-oxe810/drivers/spi/atmel_spi.c
---- linux-2.6.24/drivers/spi/atmel_spi.c       2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/spi/atmel_spi.c        2008-06-11 17:49:13.000000000 +0200
-@@ -85,6 +85,16 @@
-       unsigned gpio = (unsigned) spi->controller_data;
-       unsigned active = spi->mode & SPI_CS_HIGH;
-       u32 mr;
-+      int i;
-+      u32 csr;
-+      u32 cpol = (spi->mode & SPI_CPOL) ? SPI_BIT(CPOL) : 0;
-+
-+      /* Make sure clock polarity is correct */
-+      for (i = 0; i < spi->master->num_chipselect; i++) {
-+              csr = spi_readl(as, CSR0 + 4 * i);
-+              if ((csr ^ cpol) & SPI_BIT(CPOL))
-+                      spi_writel(as, CSR0 + 4 * i, csr ^ SPI_BIT(CPOL));
-+      }
-       mr = spi_readl(as, MR);
-       mr = SPI_BFINS(PCS, ~(1 << spi->chip_select), mr);
-diff -Nurd linux-2.6.24/drivers/spi/pxa2xx_spi.c linux-2.6.24-oxe810/drivers/spi/pxa2xx_spi.c
---- linux-2.6.24/drivers/spi/pxa2xx_spi.c      2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/spi/pxa2xx_spi.c       2008-06-11 17:49:13.000000000 +0200
-@@ -48,13 +48,19 @@
- #define RESET_DMA_CHANNEL (DCSR_NODESC | DMA_INT_MASK)
- #define IS_DMA_ALIGNED(x) (((u32)(x)&0x07)==0)
--/* for testing SSCR1 changes that require SSP restart, basically
-- * everything except the service and interrupt enables */
--#define SSCR1_CHANGE_MASK (SSCR1_TTELP | SSCR1_TTE | SSCR1_EBCEI | SSCR1_SCFR \
-+/*
-+ * for testing SSCR1 changes that require SSP restart, basically
-+ * everything except the service and interrupt enables, the pxa270 developer
-+ * manual says only SSCR1_SCFR, SSCR1_SPH, SSCR1_SPO need to be in this
-+ * list, but the PXA255 dev man says all bits without really meaning the
-+ * service and interrupt enables
-+ */
-+#define SSCR1_CHANGE_MASK (SSCR1_TTELP | SSCR1_TTE | SSCR1_SCFR \
-                               | SSCR1_ECRA | SSCR1_ECRB | SSCR1_SCLKDIR \
--                              | SSCR1_RWOT | SSCR1_TRAIL | SSCR1_PINTE \
--                              | SSCR1_STRF | SSCR1_EFWR |SSCR1_RFT \
--                              | SSCR1_TFT | SSCR1_SPH | SSCR1_SPO | SSCR1_LBM)
-+                              | SSCR1_SFRMDIR | SSCR1_RWOT | SSCR1_TRAIL \
-+                              | SSCR1_IFS | SSCR1_STRF | SSCR1_EFWR \
-+                              | SSCR1_RFT | SSCR1_TFT | SSCR1_MWDS \
-+                              | SSCR1_SPH | SSCR1_SPO | SSCR1_LBM)
- #define DEFINE_SSP_REG(reg, off) \
- static inline u32 read_##reg(void *p) { return __raw_readl(p + (off)); } \
-@@ -961,9 +967,6 @@
-               if (drv_data->ssp_type == PXA25x_SSP)
-                       DCMD(drv_data->tx_channel) |= DCMD_ENDIRQEN;
--              /* Fix me, need to handle cs polarity */
--              drv_data->cs_control(PXA2XX_CS_ASSERT);
--
-               /* Clear status and start DMA engine */
-               cr1 = chip->cr1 | dma_thresh | drv_data->dma_cr1;
-               write_SSSR(drv_data->clear_sr, reg);
-@@ -973,9 +976,6 @@
-               /* Ensure we have the correct interrupt handler */
-               drv_data->transfer_handler = interrupt_transfer;
--              /* Fix me, need to handle cs polarity */
--              drv_data->cs_control(PXA2XX_CS_ASSERT);
--
-               /* Clear status  */
-               cr1 = chip->cr1 | chip->threshold | drv_data->int_cr1;
-               write_SSSR(drv_data->clear_sr, reg);
-@@ -986,16 +986,29 @@
-               || (read_SSCR1(reg) & SSCR1_CHANGE_MASK) !=
-                       (cr1 & SSCR1_CHANGE_MASK)) {
-+              /* stop the SSP, and update the other bits */
-               write_SSCR0(cr0 & ~SSCR0_SSE, reg);
-               if (drv_data->ssp_type != PXA25x_SSP)
-                       write_SSTO(chip->timeout, reg);
--              write_SSCR1(cr1, reg);
-+              /* first set CR1 without interrupt and service enables */
-+              write_SSCR1(cr1 & SSCR1_CHANGE_MASK, reg);
-+              /* restart the SSP */
-               write_SSCR0(cr0, reg);
-+
-       } else {
-               if (drv_data->ssp_type != PXA25x_SSP)
-                       write_SSTO(chip->timeout, reg);
--              write_SSCR1(cr1, reg);
-       }
-+
-+      /* FIXME, need to handle cs polarity,
-+       * this driver uses struct pxa2xx_spi_chip.cs_control to
-+       * specify a CS handling function, and it ignores most
-+       * struct spi_device.mode[s], including SPI_CS_HIGH */
-+      drv_data->cs_control(PXA2XX_CS_ASSERT);
-+
-+      /* after chip select, release the data by enabling service
-+       * requests and interrupts, without changing any mode bits */
-+      write_SSCR1(cr1, reg);
- }
- static void pump_messages(struct work_struct *work)
-diff -Nurd linux-2.6.24/drivers/usb/Kconfig linux-2.6.24-oxe810/drivers/usb/Kconfig
---- linux-2.6.24/drivers/usb/Kconfig   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/usb/Kconfig    2008-06-11 17:50:19.000000000 +0200
-@@ -36,6 +36,7 @@
-       default y if ARCH_EP93XX
-       default y if ARCH_AT91
-       default y if ARCH_PNX4008
-+      default y if ARCH_HIPOX
-       # PPC:
-       default y if STB03xxx
-       default y if PPC_MPC52xx
-@@ -49,6 +50,7 @@
-       boolean
-       default y if PPC_83xx
-       default y if SOC_AU1200
-+      default y if ARCH_HIPOX
-       default PCI
- # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface.
-diff -Nurd linux-2.6.24/drivers/usb/class/usblp.c linux-2.6.24-oxe810/drivers/usb/class/usblp.c
---- linux-2.6.24/drivers/usb/class/usblp.c     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/usb/class/usblp.c      2008-06-11 17:50:16.000000000 +0200
-@@ -428,6 +428,7 @@
-       usblp->rcomplete = 0;
-       if (handle_bidir(usblp) < 0) {
-+              usb_autopm_put_interface(intf);
-               usblp->used = 0;
-               file->private_data = NULL;
-               retval = -EIO;
-diff -Nurd linux-2.6.24/drivers/usb/core/driver.c linux-2.6.24-oxe810/drivers/usb/core/driver.c
---- linux-2.6.24/drivers/usb/core/driver.c     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/usb/core/driver.c      2008-06-11 17:50:16.000000000 +0200
-@@ -534,8 +534,8 @@
-          id->driver_info is the way to create an entry that
-          indicates that the driver want to examine every
-          device and interface. */
--      for (; id->idVendor || id->bDeviceClass || id->bInterfaceClass ||
--             id->driver_info; id++) {
-+      for (; id->idVendor || id->idProduct || id->bDeviceClass ||
-+             id->bInterfaceClass || id->driver_info; id++) {
-               if (usb_match_one_id(interface, id))
-                       return id;
-       }
-diff -Nurd linux-2.6.24/drivers/usb/core/hcd.h linux-2.6.24-oxe810/drivers/usb/core/hcd.h
---- linux-2.6.24/drivers/usb/core/hcd.h        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/usb/core/hcd.h 2008-06-11 17:50:16.000000000 +0200
+diff -Nurd linux-2.6.24.4/drivers/usb/core/hcd.h linux-2.6.24/drivers/usb/core/hcd.h
+--- linux-2.6.24.4/drivers/usb/core/hcd.h      2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/drivers/usb/core/hcd.h        2010-01-14 14:01:15.000000000 +0100
 @@ -312,7 +312,9 @@
  #define SetHubFeature         (0x2000 | USB_REQ_SET_FEATURE)
  #define SetPortFeature                (0x2300 | USB_REQ_SET_FEATURE)
@@ -43483,65 +39875,9 @@ diff -Nurd linux-2.6.24/drivers/usb/core/hcd.h linux-2.6.24-oxe810/drivers/usb/c
  extern void usb_set_device_state(struct usb_device *udev,
                enum usb_device_state new_state);
  
-diff -Nurd linux-2.6.24/drivers/usb/core/hub.c linux-2.6.24-oxe810/drivers/usb/core/hub.c
---- linux-2.6.24/drivers/usb/core/hub.c        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/usb/core/hub.c 2008-06-11 17:50:16.000000000 +0200
-@@ -2946,7 +2946,7 @@
-               if (len < le16_to_cpu(udev->config[index].desc.wTotalLength))
-                       len = le16_to_cpu(udev->config[index].desc.wTotalLength);
-       }
--      buf = kmalloc (len, GFP_KERNEL);
-+      buf = kmalloc(len, GFP_NOIO);
-       if (buf == NULL) {
-               dev_err(&udev->dev, "no mem to re-read configs after reset\n");
-               /* assume the worst */
-diff -Nurd linux-2.6.24/drivers/usb/gadget/fsl_usb2_udc.c linux-2.6.24-oxe810/drivers/usb/gadget/fsl_usb2_udc.c
---- linux-2.6.24/drivers/usb/gadget/fsl_usb2_udc.c     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/usb/gadget/fsl_usb2_udc.c      2008-06-11 17:50:17.000000000 +0200
-@@ -776,7 +776,7 @@
-               VDBG("%s, bad params\n", __FUNCTION__);
-               return -EINVAL;
-       }
--      if (!_ep || (!ep->desc && ep_index(ep))) {
-+      if (unlikely(!_ep || !ep->desc)) {
-               VDBG("%s, bad ep\n", __FUNCTION__);
-               return -EINVAL;
-       }
-diff -Nurd linux-2.6.24/drivers/usb/host/Kconfig linux-2.6.24-oxe810/drivers/usb/host/Kconfig
---- linux-2.6.24/drivers/usb/host/Kconfig      2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/usb/host/Kconfig       2008-06-11 17:50:19.000000000 +0200
-@@ -41,6 +41,7 @@
- config USB_EHCI_ROOT_HUB_TT
-       bool "Root Hub Transaction Translators (EXPERIMENTAL)"
-       depends on USB_EHCI_HCD && EXPERIMENTAL
-+      default y if ARCH_HIPOX
-       ---help---
-         Some EHCI chips have vendor-specific extensions to integrate
-         transaction translators, so that no OHCI or UHCI companion
-diff -Nurd linux-2.6.24/drivers/usb/host/Makefile linux-2.6.24-oxe810/drivers/usb/host/Makefile
---- linux-2.6.24/drivers/usb/host/Makefile     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/usb/host/Makefile      2008-06-11 17:50:19.000000000 +0200
-@@ -3,7 +3,11 @@
- #
- ifeq ($(CONFIG_USB_DEBUG),y)
--      EXTRA_CFLAGS            += -DDEBUG
-+      EXTRA_CFLAGS            += -DDEBUG 
-+endif
-+
-+ifeq ($(CONFIG_EHCI_VERBOSE_DEBUG),y)
-+      EXTRA_CFLAGS            += -DEHCI_VERBOSE_DEBUG
- endif
- obj-$(CONFIG_PCI)             += pci-quirks.o
-@@ -16,4 +20,3 @@
- obj-$(CONFIG_USB_SL811_CS)    += sl811_cs.o
- obj-$(CONFIG_USB_U132_HCD)    += u132-hcd.o
- obj-$(CONFIG_USB_R8A66597_HCD)        += r8a66597-hcd.o
--
-diff -Nurd linux-2.6.24/drivers/usb/host/ehci-dbg.c linux-2.6.24-oxe810/drivers/usb/host/ehci-dbg.c
---- linux-2.6.24/drivers/usb/host/ehci-dbg.c   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/usb/host/ehci-dbg.c    2008-06-11 17:50:19.000000000 +0200
+diff -Nurd linux-2.6.24.4/drivers/usb/host/ehci-dbg.c linux-2.6.24/drivers/usb/host/ehci-dbg.c
+--- linux-2.6.24.4/drivers/usb/host/ehci-dbg.c 2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/drivers/usb/host/ehci-dbg.c   2010-01-14 14:01:15.000000000 +0100
 @@ -28,11 +28,11 @@
        dev_warn (ehci_to_hcd(ehci)->self.controller , fmt , ## args )
  
@@ -43649,9 +39985,75 @@ diff -Nurd linux-2.6.24/drivers/usb/host/ehci-dbg.c linux-2.6.24-oxe810/drivers/
  }
  
  #endif /* STUB_DEBUG_FILES */
-diff -Nurd linux-2.6.24/drivers/usb/host/ehci-hcd.c linux-2.6.24-oxe810/drivers/usb/host/ehci-hcd.c
---- linux-2.6.24/drivers/usb/host/ehci-hcd.c   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/usb/host/ehci-hcd.c    2008-06-11 17:50:19.000000000 +0200
+diff -Nurd linux-2.6.24.4/drivers/usb/host/ehci.h linux-2.6.24/drivers/usb/host/ehci.h
+--- linux-2.6.24.4/drivers/usb/host/ehci.h     2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/drivers/usb/host/ehci.h       2010-01-14 14:01:15.000000000 +0100
+@@ -262,14 +262,22 @@
+       /* ASYNCLISTADDR: offset 0x18 */
+       u32             async_next;     /* address of next async queue head */
+-      u32             reserved [9];
++      u32 ttctrl;
++      u32 burstsize;
++      u32 txfilltuning;
++      u32 txttfilltuning;
++      u32 reserved_1;
++      u32 ulpi_viewport;
++      u32 reserved_2;
++      u32 endpknack;
++      u32 endptnalek;
+       /* CONFIGFLAG: offset 0x40 */
+       u32             configured_flag;
+ #define FLAG_CF               (1<<0)          /* true: we'll support "high speed" */
+       /* PORTSC: offset 0x44 */
+-      u32             port_status [0];        /* up to N_PORTS */
++      u32             port_status [8];        /* up to N_PORTS, max 8 */
+ /* 31:23 reserved */
+ #define PORT_WKOC_E   (1<<22)         /* wake on overcurrent (enable) */
+ #define PORT_WKDISC_E (1<<21)         /* wake on disconnect (enable) */
+@@ -294,14 +302,22 @@
+ #define PORT_CSC      (1<<1)          /* connect status change */
+ #define PORT_CONNECT  (1<<0)          /* device connected */
+ #define PORT_RWC_BITS   (PORT_CSC | PORT_PEC | PORT_OCC)
+-} __attribute__ ((packed));
+-#define USBMODE               0x68            /* USB Device mode */
++      u32 otgsc;
++      u32 usbmode;
+ #define USBMODE_SDIS  (1<<3)          /* Stream disable */
+-#define USBMODE_BE    (1<<2)          /* BE/LE endianness select */
++#define USBMODE_BE            (1<<2)          /* BE/LE endianness select */
+ #define USBMODE_CM_HC (3<<0)          /* host controller mode */
+ #define USBMODE_CM_IDLE       (0<<0)          /* idle state */
++      u32 endptsetupstack;
++      u32 endptprime;
++      u32 endptflush;
++      u32 endptstat;
++      u32 endptcomplete;
++      u32 endptctrl[8];
++} __attribute__ ((packed));
++
+ /* Appendix C, Debug port ... intended for use with special "debug devices"
+  * that can help if there's no serial console.  (nonstandard enumeration.)
+  */
+@@ -682,6 +698,11 @@
+       }
+       return (1<<USB_PORT_FEAT_HIGHSPEED);
+ }
++#ifdef CONFIG_USB_EHCI_ROOT_HUB_TT
++/* TDI transaction translator status register and busy bit */
++#define TT_BUSY 0x1
++#define TT_STATUS  (0x15c-0x140)
++#endif
+ #else
+diff -Nurd linux-2.6.24.4/drivers/usb/host/ehci-hcd.c linux-2.6.24/drivers/usb/host/ehci-hcd.c
+--- linux-2.6.24.4/drivers/usb/host/ehci-hcd.c 2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/drivers/usb/host/ehci-hcd.c   2010-01-14 14:01:15.000000000 +0100
 @@ -197,7 +197,7 @@
        u32 __iomem     *reg_ptr;
        u32             tmp;
@@ -43719,48 +40121,9 @@ diff -Nurd linux-2.6.24/drivers/usb/host/ehci-hcd.c linux-2.6.24-oxe810/drivers/
  
  #ifdef CONFIG_USB_EHCI_FSL
  #include "ehci-fsl.c"
-diff -Nurd linux-2.6.24/drivers/usb/host/ehci-hub.c linux-2.6.24-oxe810/drivers/usb/host/ehci-hub.c
---- linux-2.6.24/drivers/usb/host/ehci-hub.c   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/usb/host/ehci-hub.c    2008-06-11 17:50:19.000000000 +0200
-@@ -769,6 +769,11 @@
-               dbg_port (ehci, "GetStatus", wIndex + 1, temp);
-               put_unaligned(cpu_to_le32 (status), (__le32 *) buf);
-               break;
-+#ifdef CONFIG_USB_EHCI_ROOT_HUB_TT
-+        case ResetHubTT :
-+                *((u32 *) ((u32)ehci->regs +TT_STATUS)) = 2;
-+                break;
-+#endif                
-       case SetHubFeature:
-               switch (wValue) {
-               case C_HUB_LOCAL_POWER:
-@@ -825,6 +830,23 @@
-                               temp |= PORT_RESET;
-                               temp &= ~PORT_PE;
-+#if defined(CONFIG_USB_EHCI_ROOT_HUB_TT) & defined (CONFIG_ARCH_HIPOX) & 0 
-+              printk(KERN_ERR "port using status raw %lx\n",temp);
-+              temp &= 0x0fffffffL; /* remove default data source */
-+              if (temp & (1 << 27 ))
-+              { 
-+                      /* set the input to the UTMI input */
-+                      temp |= 0x20000000L;
-+                      printk(KERN_ERR "port using UTMI %d\n",wIndex);
-+              }
-+              else
-+              {
-+                      /* set the input to the serial PHY input */
-+                      temp |= 0xE0000000L; 
-+                      printk(KERN_ERR "port using serial PHY %d\n",wIndex);
-+              }
-+              writel(temp, &ehci->regs->port_status [wIndex]);
-+#endif        
-                               /*
-                                * caller must wait, then call GetPortStatus
-                                * usb 2.0 spec says 50 ms resets on root
-diff -Nurd linux-2.6.24/drivers/usb/host/ehci-hipox.c linux-2.6.24-oxe810/drivers/usb/host/ehci-hipox.c
---- linux-2.6.24/drivers/usb/host/ehci-hipox.c 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/usb/host/ehci-hipox.c  2008-06-11 17:50:19.000000000 +0200
+diff -Nurd linux-2.6.24.4/drivers/usb/host/ehci-hipox.c linux-2.6.24/drivers/usb/host/ehci-hipox.c
+--- linux-2.6.24.4/drivers/usb/host/ehci-hipox.c       1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/drivers/usb/host/ehci-hipox.c 2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,307 @@
 +/*
 + * EHCI HCD (Host Controller Driver) for USB.
@@ -44069,24 +40432,48 @@ diff -Nurd linux-2.6.24/drivers/usb/host/ehci-hipox.c linux-2.6.24-oxe810/driver
 +              .name = "hipox-ehci",
 +      },
 +};
-diff -Nurd linux-2.6.24/drivers/usb/host/ehci-q.c linux-2.6.24-oxe810/drivers/usb/host/ehci-q.c
---- linux-2.6.24/drivers/usb/host/ehci-q.c     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/usb/host/ehci-q.c      2008-06-11 17:50:19.000000000 +0200
-@@ -315,10 +315,10 @@
-                       if (likely (last->urb != urb)) {
-                               ehci_urb_done(ehci, last->urb, last_status);
-                               count++;
-+                              last_status = -EINPROGRESS;
-                       }
-                       ehci_qtd_free (ehci, last);
-                       last = NULL;
--                      last_status = -EINPROGRESS;
-               }
+diff -Nurd linux-2.6.24.4/drivers/usb/host/ehci-hub.c linux-2.6.24/drivers/usb/host/ehci-hub.c
+--- linux-2.6.24.4/drivers/usb/host/ehci-hub.c 2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/drivers/usb/host/ehci-hub.c   2010-01-14 14:01:15.000000000 +0100
+@@ -769,6 +769,11 @@
+               dbg_port (ehci, "GetStatus", wIndex + 1, temp);
+               put_unaligned(cpu_to_le32 (status), (__le32 *) buf);
+               break;
++#ifdef CONFIG_USB_EHCI_ROOT_HUB_TT
++        case ResetHubTT :
++                *((u32 *) ((u32)ehci->regs +TT_STATUS)) = 2;
++                break;
++#endif                
+       case SetHubFeature:
+               switch (wValue) {
+               case C_HUB_LOCAL_POWER:
+@@ -825,6 +830,23 @@
+                               temp |= PORT_RESET;
+                               temp &= ~PORT_PE;
  
-               /* ignore urbs submitted during completions we reported */
-diff -Nurd linux-2.6.24/drivers/usb/host/ehci-sched.c linux-2.6.24-oxe810/drivers/usb/host/ehci-sched.c
---- linux-2.6.24/drivers/usb/host/ehci-sched.c 2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/usb/host/ehci-sched.c  2008-06-11 17:50:19.000000000 +0200
++#if defined(CONFIG_USB_EHCI_ROOT_HUB_TT) & defined (CONFIG_ARCH_HIPOX) & 0 
++              printk(KERN_ERR "port using status raw %lx\n",temp);
++              temp &= 0x0fffffffL; /* remove default data source */
++              if (temp & (1 << 27 ))
++              { 
++                      /* set the input to the UTMI input */
++                      temp |= 0x20000000L;
++                      printk(KERN_ERR "port using UTMI %d\n",wIndex);
++              }
++              else
++              {
++                      /* set the input to the serial PHY input */
++                      temp |= 0xE0000000L; 
++                      printk(KERN_ERR "port using serial PHY %d\n",wIndex);
++              }
++              writel(temp, &ehci->regs->port_status [wIndex]);
++#endif        
+                               /*
+                                * caller must wait, then call GetPortStatus
+                                * usb 2.0 spec says 50 ms resets on root
+diff -Nurd linux-2.6.24.4/drivers/usb/host/ehci-sched.c linux-2.6.24/drivers/usb/host/ehci-sched.c
+--- linux-2.6.24.4/drivers/usb/host/ehci-sched.c       2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/drivers/usb/host/ehci-sched.c 2010-01-14 14:01:15.000000000 +0100
 @@ -2109,6 +2109,7 @@
  {
        unsigned        frame, clock, now_uframe, mod;
@@ -44128,75 +40515,60 @@ diff -Nurd linux-2.6.24/drivers/usb/host/ehci-sched.c linux-2.6.24-oxe810/driver
  
                if (now_uframe == clock) {
                        unsigned        now;
-diff -Nurd linux-2.6.24/drivers/usb/host/ehci.h linux-2.6.24-oxe810/drivers/usb/host/ehci.h
---- linux-2.6.24/drivers/usb/host/ehci.h       2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/usb/host/ehci.h        2008-06-11 17:50:19.000000000 +0200
-@@ -262,14 +262,22 @@
-       /* ASYNCLISTADDR: offset 0x18 */
-       u32             async_next;     /* address of next async queue head */
--      u32             reserved [9];
-+      u32 ttctrl;
-+      u32 burstsize;
-+      u32 txfilltuning;
-+      u32 txttfilltuning;
-+      u32 reserved_1;
-+      u32 ulpi_viewport;
-+      u32 reserved_2;
-+      u32 endpknack;
-+      u32 endptnalek;
-       /* CONFIGFLAG: offset 0x40 */
-       u32             configured_flag;
- #define FLAG_CF               (1<<0)          /* true: we'll support "high speed" */
-       /* PORTSC: offset 0x44 */
--      u32             port_status [0];        /* up to N_PORTS */
-+      u32             port_status [8];        /* up to N_PORTS, max 8 */
- /* 31:23 reserved */
- #define PORT_WKOC_E   (1<<22)         /* wake on overcurrent (enable) */
- #define PORT_WKDISC_E (1<<21)         /* wake on disconnect (enable) */
-@@ -294,14 +302,22 @@
- #define PORT_CSC      (1<<1)          /* connect status change */
- #define PORT_CONNECT  (1<<0)          /* device connected */
- #define PORT_RWC_BITS   (PORT_CSC | PORT_PEC | PORT_OCC)
--} __attribute__ ((packed));
--#define USBMODE               0x68            /* USB Device mode */
-+      u32 otgsc;
-+      u32 usbmode;
- #define USBMODE_SDIS  (1<<3)          /* Stream disable */
--#define USBMODE_BE    (1<<2)          /* BE/LE endianness select */
-+#define USBMODE_BE            (1<<2)          /* BE/LE endianness select */
- #define USBMODE_CM_HC (3<<0)          /* host controller mode */
- #define USBMODE_CM_IDLE       (0<<0)          /* idle state */
+diff -Nurd linux-2.6.24.4/drivers/usb/host/Kconfig linux-2.6.24/drivers/usb/host/Kconfig
+--- linux-2.6.24.4/drivers/usb/host/Kconfig    2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/drivers/usb/host/Kconfig      2010-01-14 14:01:15.000000000 +0100
+@@ -41,6 +41,7 @@
+ config USB_EHCI_ROOT_HUB_TT
+       bool "Root Hub Transaction Translators (EXPERIMENTAL)"
+       depends on USB_EHCI_HCD && EXPERIMENTAL
++      default y if ARCH_HIPOX
+       ---help---
+         Some EHCI chips have vendor-specific extensions to integrate
+         transaction translators, so that no OHCI or UHCI companion
+diff -Nurd linux-2.6.24.4/drivers/usb/host/Makefile linux-2.6.24/drivers/usb/host/Makefile
+--- linux-2.6.24.4/drivers/usb/host/Makefile   2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/drivers/usb/host/Makefile     2010-01-14 14:01:15.000000000 +0100
+@@ -3,7 +3,11 @@
+ #
  
-+      u32 endptsetupstack;
-+      u32 endptprime;
-+      u32 endptflush;
-+      u32 endptstat;
-+      u32 endptcomplete;
-+      u32 endptctrl[8];
-+} __attribute__ ((packed));
+ ifeq ($(CONFIG_USB_DEBUG),y)
+-      EXTRA_CFLAGS            += -DDEBUG
++      EXTRA_CFLAGS            += -DDEBUG 
++endif
 +
- /* Appendix C, Debug port ... intended for use with special "debug devices"
-  * that can help if there's no serial console.  (nonstandard enumeration.)
-  */
-@@ -682,6 +698,11 @@
-       }
-       return (1<<USB_PORT_FEAT_HIGHSPEED);
- }
-+#ifdef CONFIG_USB_EHCI_ROOT_HUB_TT
-+/* TDI transaction translator status register and busy bit */
-+#define TT_BUSY 0x1
-+#define TT_STATUS  (0x15c-0x140)
-+#endif
++ifeq ($(CONFIG_EHCI_VERBOSE_DEBUG),y)
++      EXTRA_CFLAGS            += -DEHCI_VERBOSE_DEBUG
+ endif
  
- #else
+ obj-$(CONFIG_PCI)             += pci-quirks.o
+@@ -16,4 +20,3 @@
+ obj-$(CONFIG_USB_SL811_CS)    += sl811_cs.o
+ obj-$(CONFIG_USB_U132_HCD)    += u132-hcd.o
+ obj-$(CONFIG_USB_R8A66597_HCD)        += r8a66597-hcd.o
+-
+diff -Nurd linux-2.6.24.4/drivers/usb/Kconfig linux-2.6.24/drivers/usb/Kconfig
+--- linux-2.6.24.4/drivers/usb/Kconfig 2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/drivers/usb/Kconfig   2010-01-14 14:01:15.000000000 +0100
+@@ -36,6 +36,7 @@
+       default y if ARCH_EP93XX
+       default y if ARCH_AT91
+       default y if ARCH_PNX4008
++      default y if ARCH_HIPOX
+       # PPC:
+       default y if STB03xxx
+       default y if PPC_MPC52xx
+@@ -49,6 +50,7 @@
+       boolean
+       default y if PPC_83xx
+       default y if SOC_AU1200
++      default y if ARCH_HIPOX
+       default PCI
  
-diff -Nurd linux-2.6.24/drivers/usb/misc/usbtest.c linux-2.6.24-oxe810/drivers/usb/misc/usbtest.c
---- linux-2.6.24/drivers/usb/misc/usbtest.c    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/usb/misc/usbtest.c     2008-06-11 17:50:18.000000000 +0200
+ # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface.
+diff -Nurd linux-2.6.24.4/drivers/usb/misc/usbtest.c linux-2.6.24/drivers/usb/misc/usbtest.c
+--- linux-2.6.24.4/drivers/usb/misc/usbtest.c  2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/drivers/usb/misc/usbtest.c    2010-01-14 14:01:15.000000000 +0100
 @@ -993,6 +993,7 @@
  
                u->context = &context;
@@ -44205,15 +40577,7 @@ diff -Nurd linux-2.6.24/drivers/usb/misc/usbtest.c linux-2.6.24-oxe810/drivers/u
        }
  
        /* queue the urbs */
-@@ -1151,6 +1152,7 @@
-               dbg ("ep %02x couldn't get halt status, %d", ep, retval);
-               return retval;
-       }
-+      le16_to_cpus(&status);
-       if (status != 1) {
-               dbg ("ep %02x bogus status: %04x != 1", ep, status);
-               return -EINVAL;
-@@ -1207,7 +1209,7 @@
+@@ -1208,7 +1209,7 @@
        int             retval = 0;
        struct urb      *urb;
  
@@ -44222,7 +40586,7 @@ diff -Nurd linux-2.6.24/drivers/usb/misc/usbtest.c linux-2.6.24-oxe810/drivers/u
        if (urb == NULL)
                return -ENOMEM;
  
-@@ -2100,6 +2102,10 @@
+@@ -2101,6 +2102,10 @@
        /* EZ-USB devices which download firmware to replace (or in our
         * case augment) the default device implementation.
         */
@@ -44233,385 +40597,9 @@ diff -Nurd linux-2.6.24/drivers/usb/misc/usbtest.c linux-2.6.24-oxe810/drivers/u
  
        /* generic EZ-USB FX controller */
        { USB_DEVICE (0x0547, 0x2235),
-diff -Nurd linux-2.6.24/drivers/usb/serial/cp2101.c linux-2.6.24-oxe810/drivers/usb/serial/cp2101.c
---- linux-2.6.24/drivers/usb/serial/cp2101.c   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/usb/serial/cp2101.c    2008-06-11 17:50:15.000000000 +0200
-@@ -59,6 +59,7 @@
-       { USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */
-       { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */
-       { USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */
-+      { USB_DEVICE(0x10C4, 0x800A) }, /* SPORTident BSM7-D-USB main station */
-       { USB_DEVICE(0x10C4, 0x803B) }, /* Pololu USB-serial converter */
-       { USB_DEVICE(0x10C4, 0x8053) }, /* Enfora EDG1228 */
-       { USB_DEVICE(0x10C4, 0x8066) }, /* Argussoft In-System Programmer */
-@@ -76,8 +77,13 @@
-       { USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */
-       { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
-       { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
-+      { USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */
-+      { USB_DEVICE(0x10C4, 0xF002) }, /* Elan Digital Systems USBwave12 */
-+      { USB_DEVICE(0x10C4, 0xF003) }, /* Elan Digital Systems USBpulse100 */
-+      { USB_DEVICE(0x10C4, 0xF004) }, /* Elan Digital Systems USBcount50 */
-       { USB_DEVICE(0x10C5, 0xEA61) }, /* Silicon Labs MobiData GPRS USB Modem */
-       { USB_DEVICE(0x13AD, 0x9999) }, /* Baltech card reader */
-+      { USB_DEVICE(0x166A, 0x0303) }, /* Clipsal 5500PCU C-Bus USB interface */
-       { USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */
-       { } /* Terminating Entry */
- };
-diff -Nurd linux-2.6.24/drivers/usb/serial/ftdi_sio.c linux-2.6.24-oxe810/drivers/usb/serial/ftdi_sio.c
---- linux-2.6.24/drivers/usb/serial/ftdi_sio.c 2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/usb/serial/ftdi_sio.c  2008-06-11 17:50:15.000000000 +0200
-@@ -310,6 +310,7 @@
- };
- static int   ftdi_olimex_probe                (struct usb_serial *serial);
-+static int   ftdi_mtxorb_hack_setup   (struct usb_serial *serial);
- static void  ftdi_USB_UIRT_setup      (struct ftdi_private *priv);
- static void  ftdi_HE_TIRA1_setup      (struct ftdi_private *priv);
-@@ -317,6 +318,10 @@
-       .probe  = ftdi_olimex_probe,
- };
-+static struct ftdi_sio_quirk ftdi_mtxorb_hack_quirk = {
-+      .probe  = ftdi_mtxorb_hack_setup,
-+};
-+
- static struct ftdi_sio_quirk ftdi_USB_UIRT_quirk = {
-       .port_probe = ftdi_USB_UIRT_setup,
- };
-@@ -379,6 +384,8 @@
-       { USB_DEVICE(FTDI_VID, FTDI_MTXORB_4_PID) },
-       { USB_DEVICE(FTDI_VID, FTDI_MTXORB_5_PID) },
-       { USB_DEVICE(FTDI_VID, FTDI_MTXORB_6_PID) },
-+      { USB_DEVICE(MTXORB_VK_VID, MTXORB_VK_PID),
-+              .driver_info = (kernel_ulong_t)&ftdi_mtxorb_hack_quirk },
-       { USB_DEVICE(FTDI_VID, FTDI_PERLE_ULTRAPORT_PID) },
-       { USB_DEVICE(FTDI_VID, FTDI_PIEGROUP_PID) },
-       { USB_DEVICE(FTDI_VID, FTDI_TNC_X_PID) },
-@@ -471,30 +478,29 @@
-       { USB_DEVICE(FTDI_VID, FTDI_IBS_PEDO_PID) },
-       { USB_DEVICE(FTDI_VID, FTDI_IBS_PROD_PID) },
-       /*
--       * These will probably use user-space drivers.  Uncomment them if
--       * you need them or use the user-specified vendor/product module
--       * parameters (see ftdi_sio.h for the numbers).  Make a fuss if
--       * you think the driver should recognize any of them by default.
-+       * Due to many user requests for multiple ELV devices we enable
-+       * them by default.
-        */
--      /* { USB_DEVICE(FTDI_VID, FTDI_ELV_CLI7000_PID) }, */
--      /* { USB_DEVICE(FTDI_VID, FTDI_ELV_PPS7330_PID) }, */
--      /* { USB_DEVICE(FTDI_VID, FTDI_ELV_TFM100_PID) }, */
--      /* { USB_DEVICE(FTDI_VID, FTDI_ELV_UDF77_PID) }, */
--      /* { USB_DEVICE(FTDI_VID, FTDI_ELV_UIO88_PID) }, */
--      /* { USB_DEVICE(FTDI_VID, FTDI_ELV_UAD8_PID) }, */
--      /* { USB_DEVICE(FTDI_VID, FTDI_ELV_UDA7_PID) }, */
--      /* { USB_DEVICE(FTDI_VID, FTDI_ELV_USI2_PID) }, */
--      /* { USB_DEVICE(FTDI_VID, FTDI_ELV_T1100_PID) }, */
--      /* { USB_DEVICE(FTDI_VID, FTDI_ELV_PCD200_PID) }, */
--      /* { USB_DEVICE(FTDI_VID, FTDI_ELV_ULA200_PID) }, */
--      /* { USB_DEVICE(FTDI_VID, FTDI_ELV_CSI8_PID) }, */
--      /* { USB_DEVICE(FTDI_VID, FTDI_ELV_EM1000DL_PID) }, */
--      /* { USB_DEVICE(FTDI_VID, FTDI_ELV_PCK100_PID) }, */
--      /* { USB_DEVICE(FTDI_VID, FTDI_ELV_RFP500_PID) }, */
--      /* { USB_DEVICE(FTDI_VID, FTDI_ELV_FS20SIG_PID) }, */
--      /* { USB_DEVICE(FTDI_VID, FTDI_ELV_WS300PC_PID) }, */
--      /* { USB_DEVICE(FTDI_VID, FTDI_ELV_FHZ1300PC_PID) }, */
--      /* { USB_DEVICE(FTDI_VID, FTDI_ELV_WS500_PID) }, */
-+      { USB_DEVICE(FTDI_VID, FTDI_ELV_CLI7000_PID) },
-+      { USB_DEVICE(FTDI_VID, FTDI_ELV_PPS7330_PID) },
-+      { USB_DEVICE(FTDI_VID, FTDI_ELV_TFM100_PID) },
-+      { USB_DEVICE(FTDI_VID, FTDI_ELV_UDF77_PID) },
-+      { USB_DEVICE(FTDI_VID, FTDI_ELV_UIO88_PID) },
-+      { USB_DEVICE(FTDI_VID, FTDI_ELV_UAD8_PID) },
-+      { USB_DEVICE(FTDI_VID, FTDI_ELV_UDA7_PID) },
-+      { USB_DEVICE(FTDI_VID, FTDI_ELV_USI2_PID) },
-+      { USB_DEVICE(FTDI_VID, FTDI_ELV_T1100_PID) },
-+      { USB_DEVICE(FTDI_VID, FTDI_ELV_PCD200_PID) },
-+      { USB_DEVICE(FTDI_VID, FTDI_ELV_ULA200_PID) },
-+      { USB_DEVICE(FTDI_VID, FTDI_ELV_CSI8_PID) },
-+      { USB_DEVICE(FTDI_VID, FTDI_ELV_EM1000DL_PID) },
-+      { USB_DEVICE(FTDI_VID, FTDI_ELV_PCK100_PID) },
-+      { USB_DEVICE(FTDI_VID, FTDI_ELV_RFP500_PID) },
-+      { USB_DEVICE(FTDI_VID, FTDI_ELV_FS20SIG_PID) },
-+      { USB_DEVICE(FTDI_VID, FTDI_ELV_WS300PC_PID) },
-+      { USB_DEVICE(FTDI_VID, FTDI_ELV_FHZ1300PC_PID) },
-+      { USB_DEVICE(FTDI_VID, FTDI_ELV_EM1010PC_PID) },
-+      { USB_DEVICE(FTDI_VID, FTDI_ELV_WS500_PID) },
-       { USB_DEVICE(FTDI_VID, LINX_SDMUSBQSS_PID) },
-       { USB_DEVICE(FTDI_VID, LINX_MASTERDEVEL2_PID) },
-       { USB_DEVICE(FTDI_VID, LINX_FUTURE_0_PID) },
-@@ -545,6 +551,7 @@
-       { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16C_PID) },
-       { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16HR_PID) },
-       { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16HRC_PID) },
-+      { USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16IC_PID) },
-       { USB_DEVICE(KOBIL_VID, KOBIL_CONV_B1_PID) },
-       { USB_DEVICE(KOBIL_VID, KOBIL_CONV_KAAN_PID) },
-       { USB_DEVICE(POSIFLEX_VID, POSIFLEX_PP7000_PID) },
-@@ -569,6 +576,7 @@
-       { USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) },
-       { USB_DEVICE(FTDI_VID, FTDI_MAXSTREAM_PID) },
-       { USB_DEVICE(TML_VID, TML_USB_SERIAL_PID) },
-+      { USB_DEVICE(FTDI_VID, FTDI_ELSTER_UNICOM_PID) },
-       { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID),
-               .driver_info = (kernel_ulong_t)&ftdi_olimex_quirk },
-       { },                                    /* Optional parameter entry */
-@@ -1299,6 +1307,23 @@
-       }
-       return 0;
-+}
-+
-+/*
-+ * The Matrix Orbital VK204-25-USB has an invalid IN endpoint.
-+ * We have to correct it if we want to read from it.
-+ */
-+static int ftdi_mtxorb_hack_setup(struct usb_serial *serial)
-+{
-+      struct usb_host_endpoint *ep = serial->dev->ep_in[1];
-+      struct usb_endpoint_descriptor *ep_desc = &ep->desc;
-+
-+      if (ep->enabled && ep_desc->wMaxPacketSize == 0) {
-+              ep_desc->wMaxPacketSize = 0x40;
-+              info("Fixing invalid wMaxPacketSize on read pipe");
-+      }
-+
-+      return 0;
- }
- /* ftdi_shutdown is called from usbserial:usb_serial_disconnect
-diff -Nurd linux-2.6.24/drivers/usb/serial/ftdi_sio.h linux-2.6.24-oxe810/drivers/usb/serial/ftdi_sio.h
---- linux-2.6.24/drivers/usb/serial/ftdi_sio.h 2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/usb/serial/ftdi_sio.h  2008-06-11 17:50:15.000000000 +0200
-@@ -98,6 +98,13 @@
- #define FTDI_MTXORB_5_PID      0xFA05  /* Matrix Orbital Product Id */
- #define FTDI_MTXORB_6_PID      0xFA06  /* Matrix Orbital Product Id */
-+/*
-+ * The following are the values for the Matrix Orbital VK204-25-USB
-+ * display, which use the FT232RL.
-+ */
-+#define MTXORB_VK_VID         0x1b3d
-+#define MTXORB_VK_PID         0x0158
-+
- /* Interbiometrics USB I/O Board */
- /* Developed for Interbiometrics by Rudolf Gugler */
- #define INTERBIOMETRICS_VID              0x1209
-@@ -245,6 +252,7 @@
- #define FTDI_ELV_WS300PC_PID  0xE0F6  /* PC-Wetterstation (WS 300 PC) */
- #define FTDI_ELV_FHZ1300PC_PID        0xE0E8  /* FHZ 1300 PC */
- #define FTDI_ELV_WS500_PID    0xE0E9  /* PC-Wetterstation (WS 500) */
-+#define FTDI_ELV_EM1010PC_PID 0xE0EF  /* Engery monitor EM 1010 PC */
- /*
-  * Definitions for ID TECH (www.idt-net.com) devices
-@@ -278,6 +286,7 @@
- #define FTDI_ATIK_ATK16C_PID  0xDF32  /* ATIK ATK-16C Colour Camera */
- #define FTDI_ATIK_ATK16HR_PID 0xDF31  /* ATIK ATK-16HR Grayscale Camera */
- #define FTDI_ATIK_ATK16HRC_PID        0xDF33  /* ATIK ATK-16HRC Colour Camera */
-+#define FTDI_ATIK_ATK16IC_PID   0xDF35  /* ATIK ATK-16IC Grayscale Camera */
- /*
-  * Protego product ids
-@@ -534,6 +543,8 @@
- #define OLIMEX_VID                    0x15BA
- #define OLIMEX_ARM_USB_OCD_PID                0x0003
-+/* www.elsterelectricity.com Elster Unicom III Optical Probe */
-+#define FTDI_ELSTER_UNICOM_PID                0xE700 /* Product Id */
- /*
-  * The Mobility Lab (TML)
-diff -Nurd linux-2.6.24/drivers/usb/serial/keyspan.c linux-2.6.24-oxe810/drivers/usb/serial/keyspan.c
---- linux-2.6.24/drivers/usb/serial/keyspan.c  2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/usb/serial/keyspan.c   2008-06-11 17:50:15.000000000 +0200
-@@ -838,7 +838,7 @@
-       port = (struct usb_serial_port *) urb->context;
-       tty = port->tty;
--      if (urb->actual_length) {
-+      if (tty && urb->actual_length) {
-               /* 0x80 bit is error flag */
-               if ((data[0] & 0x80) == 0) {
-                       /* no error on any byte */
-diff -Nurd linux-2.6.24/drivers/usb/serial/kobil_sct.c linux-2.6.24-oxe810/drivers/usb/serial/kobil_sct.c
---- linux-2.6.24/drivers/usb/serial/kobil_sct.c        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/usb/serial/kobil_sct.c 2008-06-11 17:50:15.000000000 +0200
-@@ -114,6 +114,7 @@
-       .usb_driver =           &kobil_driver,
-       .id_table =             id_table,
-       .num_interrupt_in =     NUM_DONT_CARE,
-+      .num_interrupt_out =    NUM_DONT_CARE,
-       .num_bulk_in =          0,
-       .num_bulk_out =         0,
-       .num_ports =            1,
-diff -Nurd linux-2.6.24/drivers/usb/serial/option.c linux-2.6.24-oxe810/drivers/usb/serial/option.c
---- linux-2.6.24/drivers/usb/serial/option.c   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/usb/serial/option.c    2008-06-11 17:50:15.000000000 +0200
-@@ -180,6 +180,7 @@
-       { USB_DEVICE(DELL_VENDOR_ID, 0x8117) }, /* Dell Wireless 5700 Mobile Broadband CDMA/EVDO ExpressCard == Novatel Merlin XV620 CDMA/EV-DO */
-       { USB_DEVICE(DELL_VENDOR_ID, 0x8118) }, /* Dell Wireless 5510 Mobile Broadband HSDPA ExpressCard == Novatel Merlin XU870 HSDPA/3G */
-       { USB_DEVICE(DELL_VENDOR_ID, 0x8128) }, /* Dell Wireless 5700 Mobile Broadband CDMA/EVDO Mini-Card == Novatel Expedite E720 CDMA/EV-DO */
-+      { USB_DEVICE(DELL_VENDOR_ID, 0x8136) }, /* Dell Wireless HSDPA 5520 == Novatel Expedite EU860D */
-       { USB_DEVICE(DELL_VENDOR_ID, 0x8137) }, /* Dell Wireless HSDPA 5520 */
-       { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) },
-       { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) },
-diff -Nurd linux-2.6.24/drivers/usb/serial/pl2303.c linux-2.6.24-oxe810/drivers/usb/serial/pl2303.c
---- linux-2.6.24/drivers/usb/serial/pl2303.c   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/usb/serial/pl2303.c    2008-06-11 17:50:15.000000000 +0200
-@@ -65,6 +65,7 @@
-       { USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID_2080) },
-       { USB_DEVICE(MA620_VENDOR_ID, MA620_PRODUCT_ID) },
-       { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID) },
-+      { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) },
-       { USB_DEVICE(TRIPP_VENDOR_ID, TRIPP_PRODUCT_ID) },
-       { USB_DEVICE(RADIOSHACK_VENDOR_ID, RADIOSHACK_PRODUCT_ID) },
-       { USB_DEVICE(DCU10_VENDOR_ID, DCU10_PRODUCT_ID) },
-@@ -84,9 +85,10 @@
-       { USB_DEVICE(DATAPILOT_U2_VENDOR_ID, DATAPILOT_U2_PRODUCT_ID) },
-       { USB_DEVICE(BELKIN_VENDOR_ID, BELKIN_PRODUCT_ID) },
-       { USB_DEVICE(ALCOR_VENDOR_ID, ALCOR_PRODUCT_ID) },
--      { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ID) },
-       { USB_DEVICE(WS002IN_VENDOR_ID, WS002IN_PRODUCT_ID) },
-       { USB_DEVICE(COREGA_VENDOR_ID, COREGA_PRODUCT_ID) },
-+      { USB_DEVICE(HL340_VENDOR_ID, HL340_PRODUCT_ID) },
-+      { USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) },
-       { }                                     /* Terminating entry */
- };
-diff -Nurd linux-2.6.24/drivers/usb/serial/pl2303.h linux-2.6.24-oxe810/drivers/usb/serial/pl2303.h
---- linux-2.6.24/drivers/usb/serial/pl2303.h   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/usb/serial/pl2303.h    2008-06-11 17:50:15.000000000 +0200
-@@ -35,6 +35,7 @@
- #define RATOC_VENDOR_ID               0x0584
- #define RATOC_PRODUCT_ID      0xb000
-+#define RATOC_PRODUCT_ID_USB60F       0xb020
- #define TRIPP_VENDOR_ID               0x2478
- #define TRIPP_PRODUCT_ID      0x2008
-@@ -96,10 +97,6 @@
- #define ALCOR_VENDOR_ID               0x058F
- #define ALCOR_PRODUCT_ID      0x9720
--/* Huawei E620 UMTS/HSDPA card (ID: 12d1:1001) */
--#define HUAWEI_VENDOR_ID      0x12d1
--#define HUAWEI_PRODUCT_ID     0x1001
--
- /* Willcom WS002IN Data Driver (by NetIndex Inc.) */
- #define WS002IN_VENDOR_ID     0x11f6
- #define WS002IN_PRODUCT_ID    0x2001
-@@ -107,3 +104,11 @@
- /* Corega CG-USBRS232R Serial Adapter */
- #define COREGA_VENDOR_ID      0x07aa
- #define COREGA_PRODUCT_ID     0x002a
-+
-+/* HL HL-340 (ID: 4348:5523) */
-+#define HL340_VENDOR_ID               0x4348
-+#define HL340_PRODUCT_ID      0x5523
-+
-+/* Y.C. Cable U.S.A., Inc - USB to RS-232 */
-+#define YCCABLE_VENDOR_ID     0x05ad
-+#define YCCABLE_PRODUCT_ID    0x0fba
-diff -Nurd linux-2.6.24/drivers/usb/serial/sierra.c linux-2.6.24-oxe810/drivers/usb/serial/sierra.c
---- linux-2.6.24/drivers/usb/serial/sierra.c   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/usb/serial/sierra.c    2008-06-11 17:50:15.000000000 +0200
-@@ -104,6 +104,7 @@
-       { USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */
-       { USB_DEVICE(0x1199, 0x0021) }, /* Sierra Wireless AirCard 597E */
-       { USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless USB Dongle 595U */
-+      { USB_DEVICE(0x1199, 0x0023) }, /* Sierra Wireless AirCard */
-       { USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */
-       { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 */
-@@ -117,9 +118,15 @@
-       { USB_DEVICE(0x1199, 0x6851) }, /* Sierra Wireless AirCard 881 */
-       { USB_DEVICE(0x1199, 0x6852) }, /* Sierra Wireless AirCard 880 E */
-       { USB_DEVICE(0x1199, 0x6853) }, /* Sierra Wireless AirCard 881 E */
-+      { USB_DEVICE(0x1199, 0x6855) }, /* Sierra Wireless AirCard 880 U */
-+      { USB_DEVICE(0x1199, 0x6856) }, /* Sierra Wireless AirCard 881 U */
-+
-+      { USB_DEVICE(0x1199, 0x6468) }, /* Sierra Wireless MP3G - EVDO */
-+      { USB_DEVICE(0x1199, 0x6469) }, /* Sierra Wireless MP3G - UMTS/HSPA */
-       { USB_DEVICE(0x1199, 0x0112), .driver_info = DEVICE_1_PORT }, /* Sierra Wireless AirCard 580 */
-       { USB_DEVICE(0x0F3D, 0x0112), .driver_info = DEVICE_1_PORT }, /* Airprime/Sierra PC 5220 */
-+      { USB_DEVICE(0x05C6, 0x6613), .driver_info = DEVICE_1_PORT }, /* Onda H600/ZTE MF330 */
-       { USB_DEVICE(0x1199, 0x0FFF), .driver_info = DEVICE_INSTALLER},
-       { }
-@@ -129,6 +136,7 @@
- static struct usb_device_id id_table_1port [] = {
-       { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless AirCard 580 */
-       { USB_DEVICE(0x0F3D, 0x0112) }, /* AirPrime/Sierra PC 5220 */
-+      { USB_DEVICE(0x05C6, 0x6613) }, /* Onda H600/ZTE MF330 */
-       { }
- };
-@@ -142,6 +150,7 @@
-       { USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */
-       { USB_DEVICE(0x1199, 0x0021) }, /* Sierra Wireless AirCard 597E */
-       { USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless USB Dongle 595U*/
-+      { USB_DEVICE(0x1199, 0x0023) }, /* Sierra Wireless AirCard */
-       { USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */
-       { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 */
-@@ -155,6 +164,10 @@
-       { USB_DEVICE(0x1199, 0x6851) }, /* Sierra Wireless AirCard 881 */
-       { USB_DEVICE(0x1199, 0x6852) }, /* Sierra Wireless AirCard 880E */
-       { USB_DEVICE(0x1199, 0x6853) }, /* Sierra Wireless AirCard 881E */
-+      { USB_DEVICE(0x1199, 0x6855) }, /* Sierra Wireless AirCard 880 U */
-+      { USB_DEVICE(0x1199, 0x6856) }, /* Sierra Wireless AirCard 881U */
-+      { USB_DEVICE(0x1199, 0x6468) }, /* Sierra Wireless MP3G - EVDO */
-+      { USB_DEVICE(0x1199, 0x6469) }, /* Sierra Wireless MP3G - UMTS/HSPA */
-       { }
- };
-diff -Nurd linux-2.6.24/drivers/usb/storage/protocol.c linux-2.6.24-oxe810/drivers/usb/storage/protocol.c
---- linux-2.6.24/drivers/usb/storage/protocol.c        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/usb/storage/protocol.c 2008-06-11 17:50:16.000000000 +0200
-@@ -194,7 +194,7 @@
-                * and the starting offset within the page, and update
-                * the *offset and *index values for the next loop. */
-               cnt = 0;
--              while (cnt < buflen) {
-+              while (cnt < buflen && sg) {
-                       struct page *page = sg_page(sg) +
-                                       ((sg->offset + *offset) >> PAGE_SHIFT);
-                       unsigned int poff =
-@@ -249,7 +249,8 @@
-       unsigned int offset = 0;
-       struct scatterlist *sg = NULL;
--      usb_stor_access_xfer_buf(buffer, buflen, srb, &sg, &offset,
-+      buflen = min(buflen, srb->request_bufflen);
-+      buflen = usb_stor_access_xfer_buf(buffer, buflen, srb, &sg, &offset,
-                       TO_XFER_BUF);
-       if (buflen < srb->request_bufflen)
-               srb->resid = srb->request_bufflen - buflen;
-diff -Nurd linux-2.6.24/drivers/usb/storage/unusual_devs.h linux-2.6.24-oxe810/drivers/usb/storage/unusual_devs.h
---- linux-2.6.24/drivers/usb/storage/unusual_devs.h    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/drivers/usb/storage/unusual_devs.h     2008-06-11 17:50:16.000000000 +0200
-@@ -86,6 +86,14 @@
-               US_SC_8070, US_PR_USBAT, init_usbat_cd, 0),
- #endif
-+/* Reported by Grant Grundler <grundler@parisc-linux.org>
-+ * HP r707 camera in "Disk" mode with 2.00.23 or 2.00.24 firmware.
-+ */
-+UNUSUAL_DEV(  0x03f0, 0x4002, 0x0001, 0x0001,
-+              "HP",
-+              "PhotoSmart R707",
-+              US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY),
-+
- /* Reported by Sebastian Kapfer <sebastian_kapfer@gmx.net>
-  * and Olaf Hering <olh@suse.de> (different bcd's, same vendor/product)
-  * for USB floppies that need the SINGLE_LUN enforcement.
-diff -Nurd linux-2.6.24/fs/adfs/file.c linux-2.6.24-oxe810/fs/adfs/file.c
---- linux-2.6.24/fs/adfs/file.c        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/adfs/file.c 2008-06-11 17:47:02.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/adfs/file.c linux-2.6.24/fs/adfs/file.c
+--- linux-2.6.24.4/fs/adfs/file.c      2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/adfs/file.c        2010-01-14 14:01:15.000000000 +0100
 @@ -33,6 +33,7 @@
        .fsync          = file_fsync,
        .write          = do_sync_write,
@@ -44620,9 +40608,9 @@ diff -Nurd linux-2.6.24/fs/adfs/file.c linux-2.6.24-oxe810/fs/adfs/file.c
        .splice_read    = generic_file_splice_read,
  };
  
-diff -Nurd linux-2.6.24/fs/affs/file.c linux-2.6.24-oxe810/fs/affs/file.c
---- linux-2.6.24/fs/affs/file.c        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/affs/file.c 2008-06-11 17:46:52.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/affs/file.c linux-2.6.24/fs/affs/file.c
+--- linux-2.6.24.4/fs/affs/file.c      2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/affs/file.c        2010-01-14 14:01:15.000000000 +0100
 @@ -35,6 +35,7 @@
        .open           = affs_file_open,
        .release        = affs_file_release,
@@ -44631,9 +40619,9 @@ diff -Nurd linux-2.6.24/fs/affs/file.c linux-2.6.24-oxe810/fs/affs/file.c
        .splice_read    = generic_file_splice_read,
  };
  
-diff -Nurd linux-2.6.24/fs/afs/file.c linux-2.6.24-oxe810/fs/afs/file.c
---- linux-2.6.24/fs/afs/file.c 2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/afs/file.c  2008-06-11 17:46:51.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/afs/file.c linux-2.6.24/fs/afs/file.c
+--- linux-2.6.24.4/fs/afs/file.c       2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/afs/file.c 2010-01-14 14:01:15.000000000 +0100
 @@ -32,6 +32,7 @@
        .aio_read       = generic_file_aio_read,
        .aio_write      = afs_file_write,
@@ -44642,27 +40630,9 @@ diff -Nurd linux-2.6.24/fs/afs/file.c linux-2.6.24-oxe810/fs/afs/file.c
        .splice_read    = generic_file_splice_read,
        .fsync          = afs_fsync,
        .lock           = afs_lock,
-diff -Nurd linux-2.6.24/fs/aio.c linux-2.6.24-oxe810/fs/aio.c
---- linux-2.6.24/fs/aio.c      2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/aio.c       2008-06-11 17:47:10.000000000 +0200
-@@ -997,6 +997,14 @@
-       /* everything turned out well, dispose of the aiocb. */
-       ret = __aio_put_req(ctx, iocb);
-+      /*
-+       * We have to order our ring_info tail store above and test
-+       * of the wait list below outside the wait lock.  This is
-+       * like in wake_up_bit() where clearing a bit has to be
-+       * ordered with the unlocked test.
-+       */
-+      smp_mb();
-+
-       if (waitqueue_active(&ctx->wait))
-               wake_up(&ctx->wait);
-diff -Nurd linux-2.6.24/fs/bio.c linux-2.6.24-oxe810/fs/bio.c
---- linux-2.6.24/fs/bio.c      2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/bio.c       2008-06-11 17:47:10.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/bio.c linux-2.6.24/fs/bio.c
+--- linux-2.6.24.4/fs/bio.c    2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/bio.c      2010-01-14 14:01:15.000000000 +0100
 @@ -133,6 +133,7 @@
        memset(bio, 0, sizeof(*bio));
        bio->bi_flags = 1 << BIO_UPTODATE;
@@ -44679,9 +40649,9 @@ diff -Nurd linux-2.6.24/fs/bio.c linux-2.6.24-oxe810/fs/bio.c
        bio_phys_segments(q, bio);
        bio_hw_segments(q, bio);
  }
-diff -Nurd linux-2.6.24/fs/coda/file.c linux-2.6.24-oxe810/fs/coda/file.c
---- linux-2.6.24/fs/coda/file.c        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/coda/file.c 2008-06-11 17:47:09.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/coda/file.c linux-2.6.24/fs/coda/file.c
+--- linux-2.6.24.4/fs/coda/file.c      2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/coda/file.c        2010-01-14 14:01:15.000000000 +0100
 @@ -238,6 +238,7 @@
        .open           = coda_open,
        .release        = coda_release,
@@ -44690,9 +40660,9 @@ diff -Nurd linux-2.6.24/fs/coda/file.c linux-2.6.24-oxe810/fs/coda/file.c
        .splice_read    = coda_file_splice_read,
  };
  
-diff -Nurd linux-2.6.24/fs/ecryptfs/file.c linux-2.6.24-oxe810/fs/ecryptfs/file.c
---- linux-2.6.24/fs/ecryptfs/file.c    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/ecryptfs/file.c     2008-06-11 17:46:59.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/ecryptfs/file.c linux-2.6.24/fs/ecryptfs/file.c
+--- linux-2.6.24.4/fs/ecryptfs/file.c  2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/ecryptfs/file.c    2010-01-14 14:01:15.000000000 +0100
 @@ -292,6 +292,7 @@
        .release = ecryptfs_release,
        .fsync = ecryptfs_fsync,
@@ -44709,153 +40679,9 @@ diff -Nurd linux-2.6.24/fs/ecryptfs/file.c linux-2.6.24-oxe810/fs/ecryptfs/file.
        .splice_read = generic_file_splice_read,
  };
  
-diff -Nurd linux-2.6.24/fs/ecryptfs/mmap.c linux-2.6.24-oxe810/fs/ecryptfs/mmap.c
---- linux-2.6.24/fs/ecryptfs/mmap.c    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/ecryptfs/mmap.c     2008-06-11 17:46:59.000000000 +0200
-@@ -263,52 +263,102 @@
-       return 0;
- }
--/* This function must zero any hole we create */
-+/**
-+ * ecryptfs_prepare_write
-+ * @file: The eCryptfs file
-+ * @page: The eCryptfs page
-+ * @from: The start byte from which we will write
-+ * @to: The end byte to which we will write
-+ *
-+ * This function must zero any hole we create
-+ *
-+ * Returns zero on success; non-zero otherwise
-+ */
- static int ecryptfs_prepare_write(struct file *file, struct page *page,
-                                 unsigned from, unsigned to)
- {
--      int rc = 0;
-       loff_t prev_page_end_size;
-+      int rc = 0;
-       if (!PageUptodate(page)) {
--              rc = ecryptfs_read_lower_page_segment(page, page->index, 0,
--                                                    PAGE_CACHE_SIZE,
--                                                    page->mapping->host);
--              if (rc) {
--                      printk(KERN_ERR "%s: Error attemping to read lower "
--                             "page segment; rc = [%d]\n", __FUNCTION__, rc);
--                      ClearPageUptodate(page);
--                      goto out;
--              } else
-+              struct ecryptfs_crypt_stat *crypt_stat =
-+                      &ecryptfs_inode_to_private(
-+                              file->f_path.dentry->d_inode)->crypt_stat;
-+
-+              if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)
-+                  || (crypt_stat->flags & ECRYPTFS_NEW_FILE)) {
-+                      rc = ecryptfs_read_lower_page_segment(
-+                              page, page->index, 0, PAGE_CACHE_SIZE,
-+                              page->mapping->host);
-+                      if (rc) {
-+                              printk(KERN_ERR "%s: Error attemping to read "
-+                                     "lower page segment; rc = [%d]\n",
-+                                     __FUNCTION__, rc);
-+                              ClearPageUptodate(page);
-+                              goto out;
-+                      } else
-+                              SetPageUptodate(page);
-+              } else if (crypt_stat->flags & ECRYPTFS_VIEW_AS_ENCRYPTED) {
-+                      if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) {
-+                              rc = ecryptfs_copy_up_encrypted_with_header(
-+                                      page, crypt_stat);
-+                              if (rc) {
-+                                      printk(KERN_ERR "%s: Error attempting "
-+                                             "to copy the encrypted content "
-+                                             "from the lower file whilst "
-+                                             "inserting the metadata from "
-+                                             "the xattr into the header; rc "
-+                                             "= [%d]\n", __FUNCTION__, rc);
-+                                      ClearPageUptodate(page);
-+                                      goto out;
-+                              }
-+                              SetPageUptodate(page);
-+                      } else {
-+                              rc = ecryptfs_read_lower_page_segment(
-+                                      page, page->index, 0, PAGE_CACHE_SIZE,
-+                                      page->mapping->host);
-+                              if (rc) {
-+                                      printk(KERN_ERR "%s: Error reading "
-+                                             "page; rc = [%d]\n",
-+                                             __FUNCTION__, rc);
-+                                      ClearPageUptodate(page);
-+                                      goto out;
-+                              }
-+                              SetPageUptodate(page);
-+                      }
-+              } else {
-+                      rc = ecryptfs_decrypt_page(page);
-+                      if (rc) {
-+                              printk(KERN_ERR "%s: Error decrypting page "
-+                                     "at index [%ld]; rc = [%d]\n",
-+                                     __FUNCTION__, page->index, rc);
-+                              ClearPageUptodate(page);
-+                              goto out;
-+                      }
-                       SetPageUptodate(page);
-+              }
-       }
--
-       prev_page_end_size = ((loff_t)page->index << PAGE_CACHE_SHIFT);
--
--      /*
--       * If creating a page or more of holes, zero them out via truncate.
--       * Note, this will increase i_size.
--       */
-+      /* If creating a page or more of holes, zero them out via truncate.
-+       * Note, this will increase i_size. */
-       if (page->index != 0) {
-               if (prev_page_end_size > i_size_read(page->mapping->host)) {
-                       rc = ecryptfs_truncate(file->f_path.dentry,
-                                              prev_page_end_size);
-                       if (rc) {
--                              printk(KERN_ERR "Error on attempt to "
-+                              printk(KERN_ERR "%s: Error on attempt to "
-                                      "truncate to (higher) offset [%lld];"
--                                     " rc = [%d]\n", prev_page_end_size, rc);
-+                                     " rc = [%d]\n", __FUNCTION__,
-+                                     prev_page_end_size, rc);
-                               goto out;
-                       }
-               }
-       }
--      /*
--       * Writing to a new page, and creating a small hole from start of page?
--       * Zero it out.
--       */
--      if ((i_size_read(page->mapping->host) == prev_page_end_size) &&
--          (from != 0)) {
-+      /* Writing to a new page, and creating a small hole from start
-+       * of page?  Zero it out. */
-+      if ((i_size_read(page->mapping->host) == prev_page_end_size)
-+          && (from != 0))
-               zero_user_page(page, 0, PAGE_CACHE_SIZE, KM_USER0);
--      }
- out:
-       return rc;
- }
-diff -Nurd linux-2.6.24/fs/eventpoll.c linux-2.6.24-oxe810/fs/eventpoll.c
---- linux-2.6.24/fs/eventpoll.c        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/eventpoll.c 2008-06-11 17:47:10.000000000 +0200
-@@ -353,7 +353,7 @@
-       spin_unlock_irqrestore(&psw->lock, flags);
-       /* Do really wake up now */
--      wake_up(wq);
-+      wake_up_nested(wq, 1 + wake_nests);
-       /* Remove the current task from the list */
-       spin_lock_irqsave(&psw->lock, flags);
-diff -Nurd linux-2.6.24/fs/ext2/file.c linux-2.6.24-oxe810/fs/ext2/file.c
---- linux-2.6.24/fs/ext2/file.c        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/ext2/file.c 2008-06-11 17:47:06.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/ext2/file.c linux-2.6.24/fs/ext2/file.c
+--- linux-2.6.24.4/fs/ext2/file.c      2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/ext2/file.c        2010-01-14 14:01:15.000000000 +0100
 @@ -56,6 +56,7 @@
        .open           = generic_file_open,
        .release        = ext2_release_file,
@@ -44872,9 +40698,9 @@ diff -Nurd linux-2.6.24/fs/ext2/file.c linux-2.6.24-oxe810/fs/ext2/file.c
  };
  #endif
  
-diff -Nurd linux-2.6.24/fs/ext3/file.c linux-2.6.24-oxe810/fs/ext3/file.c
---- linux-2.6.24/fs/ext3/file.c        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/ext3/file.c 2008-06-11 17:47:06.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/ext3/file.c linux-2.6.24/fs/ext3/file.c
+--- linux-2.6.24.4/fs/ext3/file.c      2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/ext3/file.c        2010-01-14 14:01:15.000000000 +0100
 @@ -120,6 +120,7 @@
        .open           = generic_file_open,
        .release        = ext3_release_file,
@@ -44883,9 +40709,9 @@ diff -Nurd linux-2.6.24/fs/ext3/file.c linux-2.6.24-oxe810/fs/ext3/file.c
        .splice_read    = generic_file_splice_read,
        .splice_write   = generic_file_splice_write,
  };
-diff -Nurd linux-2.6.24/fs/ext3/ialloc.c linux-2.6.24-oxe810/fs/ext3/ialloc.c
---- linux-2.6.24/fs/ext3/ialloc.c      2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/ext3/ialloc.c       2008-06-11 17:47:06.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/ext3/ialloc.c linux-2.6.24/fs/ext3/ialloc.c
+--- linux-2.6.24.4/fs/ext3/ialloc.c    2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/ext3/ialloc.c      2010-01-14 14:01:15.000000000 +0100
 @@ -543,7 +543,16 @@
                percpu_counter_inc(&sbi->s_dirs_counter);
        sb->s_dirt = 1;
@@ -44903,9 +40729,9 @@ diff -Nurd linux-2.6.24/fs/ext3/ialloc.c linux-2.6.24-oxe810/fs/ext3/ialloc.c
        if (test_opt (sb, GRPID))
                inode->i_gid = dir->i_gid;
        else if (dir->i_mode & S_ISGID) {
-diff -Nurd linux-2.6.24/fs/ext4/file.c linux-2.6.24-oxe810/fs/ext4/file.c
---- linux-2.6.24/fs/ext4/file.c        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/ext4/file.c 2008-06-11 17:47:07.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/ext4/file.c linux-2.6.24/fs/ext4/file.c
+--- linux-2.6.24.4/fs/ext4/file.c      2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/ext4/file.c        2010-01-14 14:01:15.000000000 +0100
 @@ -120,7 +120,8 @@
        .open           = generic_file_open,
        .release        = ext4_release_file,
@@ -44916,9 +40742,9 @@ diff -Nurd linux-2.6.24/fs/ext4/file.c linux-2.6.24-oxe810/fs/ext4/file.c
        .splice_write   = generic_file_splice_write,
  };
  
-diff -Nurd linux-2.6.24/fs/fat/file.c linux-2.6.24-oxe810/fs/fat/file.c
---- linux-2.6.24/fs/fat/file.c 2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/fat/file.c  2008-06-11 17:47:05.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/fat/file.c linux-2.6.24/fs/fat/file.c
+--- linux-2.6.24.4/fs/fat/file.c       2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/fat/file.c 2010-01-14 14:01:15.000000000 +0100
 @@ -134,6 +134,7 @@
        .release        = fat_file_release,
        .ioctl          = fat_generic_ioctl,
@@ -44927,21 +40753,9 @@ diff -Nurd linux-2.6.24/fs/fat/file.c linux-2.6.24-oxe810/fs/fat/file.c
        .splice_read    = generic_file_splice_read,
  };
  
-diff -Nurd linux-2.6.24/fs/fuse/dir.c linux-2.6.24-oxe810/fs/fuse/dir.c
---- linux-2.6.24/fs/fuse/dir.c 2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/fuse/dir.c  2008-06-11 17:47:00.000000000 +0200
-@@ -905,7 +905,7 @@
-       }
-       if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
--              int err = generic_permission(inode, mask, NULL);
-+              err = generic_permission(inode, mask, NULL);
-               /* If permission is denied, try to refresh file
-                  attributes.  This is also needed, because the root
-diff -Nurd linux-2.6.24/fs/fuse/file.c linux-2.6.24-oxe810/fs/fuse/file.c
---- linux-2.6.24/fs/fuse/file.c        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/fuse/file.c 2008-06-11 17:47:00.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/fuse/file.c linux-2.6.24/fs/fuse/file.c
+--- linux-2.6.24.4/fs/fuse/file.c      2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/fuse/file.c        2010-01-14 14:01:15.000000000 +0100
 @@ -920,6 +920,7 @@
        .fsync          = fuse_fsync,
        .lock           = fuse_file_lock,
@@ -44950,9 +40764,9 @@ diff -Nurd linux-2.6.24/fs/fuse/file.c linux-2.6.24-oxe810/fs/fuse/file.c
        .splice_read    = generic_file_splice_read,
  };
  
-diff -Nurd linux-2.6.24/fs/gfs2/ops_file.c linux-2.6.24-oxe810/fs/gfs2/ops_file.c
---- linux-2.6.24/fs/gfs2/ops_file.c    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/gfs2/ops_file.c     2008-06-11 17:47:09.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/gfs2/ops_file.c linux-2.6.24/fs/gfs2/ops_file.c
+--- linux-2.6.24.4/fs/gfs2/ops_file.c  2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/gfs2/ops_file.c    2010-01-14 14:01:15.000000000 +0100
 @@ -662,6 +662,7 @@
        .release        = gfs2_close,
        .fsync          = gfs2_fsync,
@@ -44961,9 +40775,9 @@ diff -Nurd linux-2.6.24/fs/gfs2/ops_file.c linux-2.6.24-oxe810/fs/gfs2/ops_file.
        .flock          = gfs2_flock,
        .splice_read    = generic_file_splice_read,
        .splice_write   = generic_file_splice_write,
-diff -Nurd linux-2.6.24/fs/hpfs/file.c linux-2.6.24-oxe810/fs/hpfs/file.c
---- linux-2.6.24/fs/hpfs/file.c        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/hpfs/file.c 2008-06-11 17:46:57.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/hpfs/file.c linux-2.6.24/fs/hpfs/file.c
+--- linux-2.6.24.4/fs/hpfs/file.c      2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/hpfs/file.c        2010-01-14 14:01:15.000000000 +0100
 @@ -137,6 +137,7 @@
        .mmap           = generic_file_mmap,
        .release        = hpfs_file_release,
@@ -44972,66 +40786,9 @@ diff -Nurd linux-2.6.24/fs/hpfs/file.c linux-2.6.24-oxe810/fs/hpfs/file.c
        .splice_read    = generic_file_splice_read,
  };
  
-diff -Nurd linux-2.6.24/fs/inotify_user.c linux-2.6.24-oxe810/fs/inotify_user.c
---- linux-2.6.24/fs/inotify_user.c     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/inotify_user.c      2008-06-11 17:47:10.000000000 +0200
-@@ -269,7 +269,7 @@
-       /* we can safely put the watch as we don't reference it while
-        * generating the event
-        */
--      if (mask & IN_IGNORED || mask & IN_ONESHOT)
-+      if (mask & IN_IGNORED || w->mask & IN_ONESHOT)
-               put_inotify_watch(w); /* final put */
-       /* coalescing: drop this event if it is a dupe of the previous */
-diff -Nurd linux-2.6.24/fs/isofs/compress.c linux-2.6.24-oxe810/fs/isofs/compress.c
---- linux-2.6.24/fs/isofs/compress.c   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/isofs/compress.c    2008-06-11 17:46:52.000000000 +0200
-@@ -72,6 +72,17 @@
-       offset = index & ~zisofs_block_page_mask;
-       blockindex = offset >> zisofs_block_page_shift;
-       maxpage = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
-+
-+      /*
-+       * If this page is wholly outside i_size we just return zero;
-+       * do_generic_file_read() will handle this for us
-+       */
-+      if (page->index >= maxpage) {
-+              SetPageUptodate(page);
-+              unlock_page(page);
-+              return 0;
-+      }
-+
-       maxpage = min(zisofs_block_pages, maxpage-offset);
-       for ( i = 0 ; i < maxpage ; i++, offset++ ) {
-diff -Nurd linux-2.6.24/fs/jbd/recovery.c linux-2.6.24-oxe810/fs/jbd/recovery.c
---- linux-2.6.24/fs/jbd/recovery.c     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/jbd/recovery.c      2008-06-11 17:47:07.000000000 +0200
-@@ -478,7 +478,7 @@
-                                       memcpy(nbh->b_data, obh->b_data,
-                                                       journal->j_blocksize);
-                                       if (flags & JFS_FLAG_ESCAPE) {
--                                              *((__be32 *)bh->b_data) =
-+                                              *((__be32 *)nbh->b_data) =
-                                               cpu_to_be32(JFS_MAGIC_NUMBER);
-                                       }
-diff -Nurd linux-2.6.24/fs/jbd2/recovery.c linux-2.6.24-oxe810/fs/jbd2/recovery.c
---- linux-2.6.24/fs/jbd2/recovery.c    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/jbd2/recovery.c     2008-06-11 17:46:49.000000000 +0200
-@@ -488,7 +488,7 @@
-                                       memcpy(nbh->b_data, obh->b_data,
-                                                       journal->j_blocksize);
-                                       if (flags & JBD2_FLAG_ESCAPE) {
--                                              *((__be32 *)bh->b_data) =
-+                                              *((__be32 *)nbh->b_data) =
-                                               cpu_to_be32(JBD2_MAGIC_NUMBER);
-                                       }
-diff -Nurd linux-2.6.24/fs/jffs2/file.c linux-2.6.24-oxe810/fs/jffs2/file.c
---- linux-2.6.24/fs/jffs2/file.c       2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/jffs2/file.c        2008-06-11 17:47:10.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/jffs2/file.c linux-2.6.24/fs/jffs2/file.c
+--- linux-2.6.24.4/fs/jffs2/file.c     2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/jffs2/file.c       2010-01-14 14:01:15.000000000 +0100
 @@ -49,7 +49,8 @@
        .ioctl =        jffs2_ioctl,
        .mmap =         generic_file_readonly_mmap,
@@ -45042,9 +40799,9 @@ diff -Nurd linux-2.6.24/fs/jffs2/file.c linux-2.6.24-oxe810/fs/jffs2/file.c
  };
  
  /* jffs2_file_inode_operations */
-diff -Nurd linux-2.6.24/fs/jfs/file.c linux-2.6.24-oxe810/fs/jfs/file.c
---- linux-2.6.24/fs/jfs/file.c 2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/jfs/file.c  2008-06-11 17:46:58.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/jfs/file.c linux-2.6.24/fs/jfs/file.c
+--- linux-2.6.24.4/fs/jfs/file.c       2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/jfs/file.c 2010-01-14 14:01:15.000000000 +0100
 @@ -108,6 +108,7 @@
        .aio_read       = generic_file_aio_read,
        .aio_write      = generic_file_aio_write,
@@ -45053,9 +40810,9 @@ diff -Nurd linux-2.6.24/fs/jfs/file.c linux-2.6.24-oxe810/fs/jfs/file.c
        .splice_read    = generic_file_splice_read,
        .splice_write   = generic_file_splice_write,
        .fsync          = jfs_fsync,
-diff -Nurd linux-2.6.24/fs/minix/file.c linux-2.6.24-oxe810/fs/minix/file.c
---- linux-2.6.24/fs/minix/file.c       2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/minix/file.c        2008-06-11 17:47:00.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/minix/file.c linux-2.6.24/fs/minix/file.c
+--- linux-2.6.24.4/fs/minix/file.c     2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/minix/file.c       2010-01-14 14:01:15.000000000 +0100
 @@ -23,6 +23,7 @@
        .aio_write      = generic_file_aio_write,
        .mmap           = generic_file_mmap,
@@ -45064,89 +40821,9 @@ diff -Nurd linux-2.6.24/fs/minix/file.c linux-2.6.24-oxe810/fs/minix/file.c
        .splice_read    = generic_file_splice_read,
  };
  
-diff -Nurd linux-2.6.24/fs/ncpfs/mmap.c linux-2.6.24-oxe810/fs/ncpfs/mmap.c
---- linux-2.6.24/fs/ncpfs/mmap.c       2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/ncpfs/mmap.c        2008-06-11 17:47:09.000000000 +0200
-@@ -50,10 +50,6 @@
-       pos = vmf->pgoff << PAGE_SHIFT;
-       count = PAGE_SIZE;
--      if ((unsigned long)vmf->virtual_address + PAGE_SIZE > area->vm_end) {
--              WARN_ON(1); /* shouldn't happen? */
--              count = area->vm_end - (unsigned long)vmf->virtual_address;
--      }
-       /* what we can read in one go */
-       bufsize = NCP_SERVER(inode)->buffer_size;
-diff -Nurd linux-2.6.24/fs/nfs/write.c linux-2.6.24-oxe810/fs/nfs/write.c
---- linux-2.6.24/fs/nfs/write.c        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/nfs/write.c 2008-06-11 17:46:59.000000000 +0200
-@@ -701,6 +701,17 @@
- }
- /*
-+ * If the page cache is marked as unsafe or invalid, then we can't rely on
-+ * the PageUptodate() flag. In this case, we will need to turn off
-+ * write optimisations that depend on the page contents being correct.
-+ */
-+static int nfs_write_pageuptodate(struct page *page, struct inode *inode)
-+{
-+      return PageUptodate(page) &&
-+              !(NFS_I(inode)->cache_validity & (NFS_INO_REVAL_PAGECACHE|NFS_INO_INVALID_DATA));
-+}
-+
-+/*
-  * Update and possibly write a cached page of an NFS file.
-  *
-  * XXX: Keep an eye on generic_file_read to make sure it doesn't do bad
-@@ -721,10 +732,13 @@
-               (long long)(page_offset(page) +offset));
-       /* If we're not using byte range locks, and we know the page
--       * is entirely in cache, it may be more efficient to avoid
--       * fragmenting write requests.
-+       * is up to date, it may be more efficient to extend the write
-+       * to cover the entire page in order to avoid fragmentation
-+       * inefficiencies.
-        */
--      if (PageUptodate(page) && inode->i_flock == NULL && !(file->f_mode & O_SYNC)) {
-+      if (nfs_write_pageuptodate(page, inode) &&
-+                      inode->i_flock == NULL &&
-+                      !(file->f_mode & O_SYNC)) {
-               count = max(count + offset, nfs_page_length(page));
-               offset = 0;
-       }
-diff -Nurd linux-2.6.24/fs/nfsd/nfsfh.c linux-2.6.24-oxe810/fs/nfsd/nfsfh.c
---- linux-2.6.24/fs/nfsd/nfsfh.c       2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/nfsd/nfsfh.c        2008-06-11 17:47:05.000000000 +0200
-@@ -231,6 +231,7 @@
-               fhp->fh_dentry = dentry;
-               fhp->fh_export = exp;
-               nfsd_nr_verified++;
-+              cache_get(&exp->h);
-       } else {
-               /*
-                * just rechecking permissions
-@@ -240,6 +241,7 @@
-               dprintk("nfsd: fh_verify - just checking\n");
-               dentry = fhp->fh_dentry;
-               exp = fhp->fh_export;
-+              cache_get(&exp->h);
-               /*
-                * Set user creds for this exportpoint; necessary even
-                * in the "just checking" case because this may be a
-@@ -251,8 +253,6 @@
-               if (error)
-                       goto out;
-       }
--      cache_get(&exp->h);
--
-       error = nfsd_mode_check(rqstp, dentry->d_inode->i_mode, type);
-       if (error)
-diff -Nurd linux-2.6.24/fs/ntfs/file.c linux-2.6.24-oxe810/fs/ntfs/file.c
---- linux-2.6.24/fs/ntfs/file.c        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/ntfs/file.c 2008-06-11 17:47:01.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/ntfs/file.c linux-2.6.24/fs/ntfs/file.c
+--- linux-2.6.24.4/fs/ntfs/file.c      2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/ntfs/file.c        2010-01-14 14:01:15.000000000 +0100
 @@ -2274,16 +2274,11 @@
                                                    mounted filesystem. */
        .mmap           = generic_file_mmap,     /* Mmap file. */
@@ -45165,9 +40842,9 @@ diff -Nurd linux-2.6.24/fs/ntfs/file.c linux-2.6.24-oxe810/fs/ntfs/file.c
  };
  
  const struct inode_operations ntfs_file_inode_ops = {
-diff -Nurd linux-2.6.24/fs/ocfs2/file.c linux-2.6.24-oxe810/fs/ocfs2/file.c
---- linux-2.6.24/fs/ocfs2/file.c       2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/ocfs2/file.c        2008-06-11 17:46:56.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/ocfs2/file.c linux-2.6.24/fs/ocfs2/file.c
+--- linux-2.6.24.4/fs/ocfs2/file.c     2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/ocfs2/file.c       2010-01-14 14:01:15.000000000 +0100
 @@ -2206,6 +2206,7 @@
  const struct file_operations ocfs2_fops = {
        .read           = do_sync_read,
@@ -45176,9 +40853,9 @@ diff -Nurd linux-2.6.24/fs/ocfs2/file.c linux-2.6.24-oxe810/fs/ocfs2/file.c
        .mmap           = ocfs2_mmap,
        .fsync          = ocfs2_sync_file,
        .release        = ocfs2_file_release,
-diff -Nurd linux-2.6.24/fs/qnx4/file.c linux-2.6.24-oxe810/fs/qnx4/file.c
---- linux-2.6.24/fs/qnx4/file.c        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/qnx4/file.c 2008-06-11 17:46:56.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/qnx4/file.c linux-2.6.24/fs/qnx4/file.c
+--- linux-2.6.24.4/fs/qnx4/file.c      2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/qnx4/file.c        2010-01-14 14:01:15.000000000 +0100
 @@ -25,6 +25,7 @@
        .read           = do_sync_read,
        .aio_read       = generic_file_aio_read,
@@ -45187,9 +40864,9 @@ diff -Nurd linux-2.6.24/fs/qnx4/file.c linux-2.6.24-oxe810/fs/qnx4/file.c
        .splice_read    = generic_file_splice_read,
  #ifdef CONFIG_QNX4FS_RW
        .write          = do_sync_write,
-diff -Nurd linux-2.6.24/fs/read_write.c linux-2.6.24-oxe810/fs/read_write.c
---- linux-2.6.24/fs/read_write.c       2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/read_write.c        2008-06-11 17:47:10.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/read_write.c linux-2.6.24/fs/read_write.c
+--- linux-2.6.24.4/fs/read_write.c     2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/read_write.c       2010-01-14 14:01:15.000000000 +0100
 @@ -26,7 +26,8 @@
        .read           = do_sync_read,
        .aio_read       = generic_file_aio_read,
@@ -45235,9 +40912,9 @@ diff -Nurd linux-2.6.24/fs/read_write.c linux-2.6.24-oxe810/fs/read_write.c
  
        if (retval > 0) {
                add_rchar(current, retval);
-diff -Nurd linux-2.6.24/fs/reiserfs/file.c linux-2.6.24-oxe810/fs/reiserfs/file.c
---- linux-2.6.24/fs/reiserfs/file.c    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/reiserfs/file.c     2008-06-11 17:46:50.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/reiserfs/file.c linux-2.6.24/fs/reiserfs/file.c
+--- linux-2.6.24.4/fs/reiserfs/file.c  2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/reiserfs/file.c    2010-01-14 14:01:15.000000000 +0100
 @@ -292,6 +292,7 @@
        .open = generic_file_open,
        .release = reiserfs_file_release,
@@ -45246,9 +40923,9 @@ diff -Nurd linux-2.6.24/fs/reiserfs/file.c linux-2.6.24-oxe810/fs/reiserfs/file.
        .aio_read = generic_file_aio_read,
        .aio_write = generic_file_aio_write,
        .splice_read = generic_file_splice_read,
-diff -Nurd linux-2.6.24/fs/smbfs/file.c linux-2.6.24-oxe810/fs/smbfs/file.c
---- linux-2.6.24/fs/smbfs/file.c       2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/smbfs/file.c        2008-06-11 17:47:00.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/smbfs/file.c linux-2.6.24/fs/smbfs/file.c
+--- linux-2.6.24.4/fs/smbfs/file.c     2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/smbfs/file.c       2010-01-14 14:01:15.000000000 +0100
 @@ -283,6 +283,27 @@
        return status;
  }
@@ -45285,43 +40962,9 @@ diff -Nurd linux-2.6.24/fs/smbfs/file.c linux-2.6.24-oxe810/fs/smbfs/file.c
        .splice_read    = smb_file_splice_read,
  };
  
-diff -Nurd linux-2.6.24/fs/splice.c linux-2.6.24-oxe810/fs/splice.c
---- linux-2.6.24/fs/splice.c   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/splice.c    2008-06-11 17:47:10.000000000 +0200
-@@ -1184,6 +1184,9 @@
- {
-       int partial;
-+      if (!access_ok(VERIFY_READ, src, n))
-+              return -EFAULT;
-+
-       pagefault_disable();
-       partial = __copy_from_user_inatomic(dst, src, n);
-       pagefault_enable();
-@@ -1236,7 +1239,7 @@
-               if (unlikely(!len))
-                       break;
-               error = -EFAULT;
--              if (unlikely(!base))
-+              if (!access_ok(VERIFY_READ, base, len))
-                       break;
-               /*
-@@ -1391,6 +1394,11 @@
-                       error = -EFAULT;
-                       break;
-               }
-+
-+              if (unlikely(!access_ok(VERIFY_WRITE, base, len))) {
-+                      error = -EFAULT;
-+                      break;
-+              }
-               sd.len = 0;
-               sd.total_len = len;
-diff -Nurd linux-2.6.24/fs/sysv/file.c linux-2.6.24-oxe810/fs/sysv/file.c
---- linux-2.6.24/fs/sysv/file.c        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/sysv/file.c 2008-06-11 17:47:00.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/sysv/file.c linux-2.6.24/fs/sysv/file.c
+--- linux-2.6.24.4/fs/sysv/file.c      2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/sysv/file.c        2010-01-14 14:01:15.000000000 +0100
 @@ -27,6 +27,7 @@
        .aio_write      = generic_file_aio_write,
        .mmap           = generic_file_mmap,
@@ -45330,9 +40973,9 @@ diff -Nurd linux-2.6.24/fs/sysv/file.c linux-2.6.24-oxe810/fs/sysv/file.c
        .splice_read    = generic_file_splice_read,
  };
  
-diff -Nurd linux-2.6.24/fs/udf/file.c linux-2.6.24-oxe810/fs/udf/file.c
---- linux-2.6.24/fs/udf/file.c 2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/udf/file.c  2008-06-11 17:47:10.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/udf/file.c linux-2.6.24/fs/udf/file.c
+--- linux-2.6.24.4/fs/udf/file.c       2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/udf/file.c 2010-01-14 14:01:15.000000000 +0100
 @@ -246,6 +246,8 @@
        .aio_write              = udf_file_aio_write,
        .release                = udf_release_file,
@@ -45342,9 +40985,9 @@ diff -Nurd linux-2.6.24/fs/udf/file.c linux-2.6.24-oxe810/fs/udf/file.c
        .splice_read            = generic_file_splice_read,
  };
  
-diff -Nurd linux-2.6.24/fs/ufs/file.c linux-2.6.24-oxe810/fs/ufs/file.c
---- linux-2.6.24/fs/ufs/file.c 2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/ufs/file.c  2008-06-11 17:46:54.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/ufs/file.c linux-2.6.24/fs/ufs/file.c
+--- linux-2.6.24.4/fs/ufs/file.c       2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/ufs/file.c 2010-01-14 14:01:15.000000000 +0100
 @@ -63,5 +63,6 @@
        .mmap           = generic_file_mmap,
        .open           = generic_file_open,
@@ -45352,45 +40995,9 @@ diff -Nurd linux-2.6.24/fs/ufs/file.c linux-2.6.24-oxe810/fs/ufs/file.c
 +      .sendfile       = generic_file_sendfile,
        .splice_read    = generic_file_splice_read,
  };
-diff -Nurd linux-2.6.24/fs/ufs/util.h linux-2.6.24-oxe810/fs/ufs/util.h
---- linux-2.6.24/fs/ufs/util.h 2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/ufs/util.h  2008-06-11 17:46:54.000000000 +0200
-@@ -58,7 +58,7 @@
- {
-       switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) {
-       case UFS_ST_SUNOS:
--              if (fs32_to_cpu(sb, usb3->fs_postblformat == UFS_42POSTBLFMT)) {
-+              if (fs32_to_cpu(sb, usb3->fs_postblformat) == UFS_42POSTBLFMT) {
-                       usb1->fs_u0.fs_sun.fs_state = cpu_to_fs32(sb, value);
-                       break;
-               }
-diff -Nurd linux-2.6.24/fs/xfs/Makefile-linux-2.6 linux-2.6.24-oxe810/fs/xfs/Makefile-linux-2.6
---- linux-2.6.24/fs/xfs/Makefile-linux-2.6     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/xfs/Makefile-linux-2.6      2008-06-11 17:46:48.000000000 +0200
-@@ -15,13 +15,20 @@
- # along with this program; if not, write the Free Software Foundation,
- # Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- #
-+CONFIG_XFS_DEBUG := n
-+CONFIG_XFS_TRACE := n
- EXTRA_CFLAGS +=        -Ifs/xfs -Ifs/xfs/linux-2.6 -funsigned-char
- XFS_LINUX := linux-2.6
-+ifeq ($(CONFIG_XFS_TRACE),y)
-+      EXTRA_CFLAGS += -DCONFIG_XFS_TRACE
-+endif
-+
- ifeq ($(CONFIG_XFS_DEBUG),y)
-       EXTRA_CFLAGS += -g
-+      EXTRA_CFLAGS += -DCONFIG_XFS_DEBUG
- endif
- obj-$(CONFIG_XFS_FS)          += xfs.o
-diff -Nurd linux-2.6.24/fs/xfs/linux-2.6/xfs_buf.c linux-2.6.24-oxe810/fs/xfs/linux-2.6/xfs_buf.c
---- linux-2.6.24/fs/xfs/linux-2.6/xfs_buf.c    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/xfs/linux-2.6/xfs_buf.c     2008-06-11 17:46:46.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/xfs/linux-2.6/xfs_buf.c linux-2.6.24/fs/xfs/linux-2.6/xfs_buf.c
+--- linux-2.6.24.4/fs/xfs/linux-2.6/xfs_buf.c  2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/xfs/linux-2.6/xfs_buf.c    2010-01-14 14:01:15.000000000 +0100
 @@ -330,20 +330,26 @@
  
        ASSERT(list_empty(&bp->b_hash_list));
@@ -45490,9 +41097,9 @@ diff -Nurd linux-2.6.24/fs/xfs/linux-2.6/xfs_buf.c linux-2.6.24-oxe810/fs/xfs/li
   fail:
        return NULL;
  }
-diff -Nurd linux-2.6.24/fs/xfs/linux-2.6/xfs_buf.h linux-2.6.24-oxe810/fs/xfs/linux-2.6/xfs_buf.h
---- linux-2.6.24/fs/xfs/linux-2.6/xfs_buf.h    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/xfs/linux-2.6/xfs_buf.h     2008-06-11 17:46:46.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/xfs/linux-2.6/xfs_buf.h linux-2.6.24/fs/xfs/linux-2.6/xfs_buf.h
+--- linux-2.6.24.4/fs/xfs/linux-2.6/xfs_buf.h  2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/xfs/linux-2.6/xfs_buf.h    2010-01-14 14:01:15.000000000 +0100
 @@ -63,7 +63,7 @@
  
        /* flags used only internally */
@@ -45502,9 +41109,9 @@ diff -Nurd linux-2.6.24/fs/xfs/linux-2.6/xfs_buf.h linux-2.6.24-oxe810/fs/xfs/li
        _XBF_RUN_QUEUES = (1 << 19),/* run block device task queue         */
        _XBF_DELWRI_Q = (1 << 21),   /* buffer on delwri queue             */
  } xfs_buf_flags_t;
-diff -Nurd linux-2.6.24/fs/xfs/linux-2.6/xfs_file.c linux-2.6.24-oxe810/fs/xfs/linux-2.6/xfs_file.c
---- linux-2.6.24/fs/xfs/linux-2.6/xfs_file.c   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/xfs/linux-2.6/xfs_file.c    2008-06-11 17:46:46.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/xfs/linux-2.6/xfs_file.c linux-2.6.24/fs/xfs/linux-2.6/xfs_file.c
+--- linux-2.6.24.4/fs/xfs/linux-2.6/xfs_file.c 2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/xfs/linux-2.6/xfs_file.c   2010-01-14 14:01:15.000000000 +0100
 @@ -122,6 +122,28 @@
  }
  
@@ -45534,25 +41141,7 @@ diff -Nurd linux-2.6.24/fs/xfs/linux-2.6/xfs_file.c linux-2.6.24-oxe810/fs/xfs/l
  xfs_file_splice_read(
        struct file             *infilp,
        loff_t                  *ppos,
-@@ -350,8 +372,8 @@
-               size = buf.used;
-               de = (struct hack_dirent *)buf.dirent;
--              curr_offset = de->offset /* & 0x7fffffff */;
-               while (size > 0) {
-+                      curr_offset = de->offset /* & 0x7fffffff */;
-                       if (filldir(dirent, de->name, de->namlen,
-                                       curr_offset & 0x7fffffff,
-                                       de->ino, de->d_type)) {
-@@ -362,7 +384,6 @@
-                                      sizeof(u64));
-                       size -= reclen;
-                       de = (struct hack_dirent *)((char *)de + reclen);
--                      curr_offset = de->offset /* & 0x7fffffff */;
-               }
-       }
-@@ -502,8 +523,11 @@
+@@ -501,8 +523,11 @@
        .llseek         = generic_file_llseek,
        .read           = do_sync_read,
        .write          = do_sync_write,
@@ -45564,7 +41153,7 @@ diff -Nurd linux-2.6.24/fs/xfs/linux-2.6/xfs_file.c linux-2.6.24-oxe810/fs/xfs/l
        .splice_read    = xfs_file_splice_read,
        .splice_write   = xfs_file_splice_write,
        .unlocked_ioctl = xfs_file_ioctl,
-@@ -525,6 +549,7 @@
+@@ -524,6 +549,7 @@
        .write          = do_sync_write,
        .aio_read       = xfs_file_aio_read_invis,
        .aio_write      = xfs_file_aio_write_invis,
@@ -45572,9 +41161,9 @@ diff -Nurd linux-2.6.24/fs/xfs/linux-2.6/xfs_file.c linux-2.6.24-oxe810/fs/xfs/l
        .splice_read    = xfs_file_splice_read_invis,
        .splice_write   = xfs_file_splice_write_invis,
        .unlocked_ioctl = xfs_file_ioctl_invis,
-diff -Nurd linux-2.6.24/fs/xfs/linux-2.6/xfs_lrw.c linux-2.6.24-oxe810/fs/xfs/linux-2.6/xfs_lrw.c
---- linux-2.6.24/fs/xfs/linux-2.6/xfs_lrw.c    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/xfs/linux-2.6/xfs_lrw.c     2008-06-11 17:46:46.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/xfs/linux-2.6/xfs_lrw.c linux-2.6.24/fs/xfs/linux-2.6/xfs_lrw.c
+--- linux-2.6.24.4/fs/xfs/linux-2.6/xfs_lrw.c  2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/xfs/linux-2.6/xfs_lrw.c    2010-01-14 14:01:15.000000000 +0100
 @@ -271,6 +271,48 @@
  }
  
@@ -45624,73 +41213,33 @@ diff -Nurd linux-2.6.24/fs/xfs/linux-2.6/xfs_lrw.c linux-2.6.24-oxe810/fs/xfs/li
  xfs_splice_read(
        xfs_inode_t             *ip,
        struct file             *infilp,
-diff -Nurd linux-2.6.24/fs/xfs/xfs_alloc.c linux-2.6.24-oxe810/fs/xfs/xfs_alloc.c
---- linux-2.6.24/fs/xfs/xfs_alloc.c    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/xfs/xfs_alloc.c     2008-06-11 17:46:48.000000000 +0200
-@@ -592,7 +592,7 @@
-               if (!(args->wasfromfl)) {
+diff -Nurd linux-2.6.24.4/fs/xfs/Makefile-linux-2.6 linux-2.6.24/fs/xfs/Makefile-linux-2.6
+--- linux-2.6.24.4/fs/xfs/Makefile-linux-2.6   2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/xfs/Makefile-linux-2.6     2010-01-14 14:01:15.000000000 +0100
+@@ -15,13 +15,20 @@
+ # along with this program; if not, write the Free Software Foundation,
+ # Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ #
++CONFIG_XFS_DEBUG := n
++CONFIG_XFS_TRACE := n
  
-                       agf = XFS_BUF_TO_AGF(args->agbp);
--                      be32_add(&agf->agf_freeblks, -(args->len));
-+                      be32_add_cpu(&agf->agf_freeblks, -(args->len));
-                       xfs_trans_agblocks_delta(args->tp,
-                                                -((long)(args->len)));
-                       args->pag->pagf_freeblks -= args->len;
-@@ -1720,7 +1720,7 @@
+ EXTRA_CFLAGS +=        -Ifs/xfs -Ifs/xfs/linux-2.6 -funsigned-char
  
-               agf = XFS_BUF_TO_AGF(agbp);
-               pag = &mp->m_perag[agno];
--              be32_add(&agf->agf_freeblks, len);
-+              be32_add_cpu(&agf->agf_freeblks, len);
-               xfs_trans_agblocks_delta(tp, len);
-               pag->pagf_freeblks += len;
-               XFS_WANT_CORRUPTED_GOTO(
-@@ -2008,18 +2008,18 @@
-        * Get the block number and update the data structures.
-        */
-       bno = be32_to_cpu(agfl->agfl_bno[be32_to_cpu(agf->agf_flfirst)]);
--      be32_add(&agf->agf_flfirst, 1);
-+      be32_add_cpu(&agf->agf_flfirst, 1);
-       xfs_trans_brelse(tp, agflbp);
-       if (be32_to_cpu(agf->agf_flfirst) == XFS_AGFL_SIZE(mp))
-               agf->agf_flfirst = 0;
-       pag = &mp->m_perag[be32_to_cpu(agf->agf_seqno)];
--      be32_add(&agf->agf_flcount, -1);
-+      be32_add_cpu(&agf->agf_flcount, -1);
-       xfs_trans_agflist_delta(tp, -1);
-       pag->pagf_flcount--;
+ XFS_LINUX := linux-2.6
  
-       logflags = XFS_AGF_FLFIRST | XFS_AGF_FLCOUNT;
-       if (btreeblk) {
--              be32_add(&agf->agf_btreeblks, 1);
-+              be32_add_cpu(&agf->agf_btreeblks, 1);
-               pag->pagf_btreeblks++;
-               logflags |= XFS_AGF_BTREEBLKS;
-       }
-@@ -2117,17 +2117,17 @@
-                       be32_to_cpu(agf->agf_seqno), &agflbp)))
-               return error;
-       agfl = XFS_BUF_TO_AGFL(agflbp);
--      be32_add(&agf->agf_fllast, 1);
-+      be32_add_cpu(&agf->agf_fllast, 1);
-       if (be32_to_cpu(agf->agf_fllast) == XFS_AGFL_SIZE(mp))
-               agf->agf_fllast = 0;
-       pag = &mp->m_perag[be32_to_cpu(agf->agf_seqno)];
--      be32_add(&agf->agf_flcount, 1);
-+      be32_add_cpu(&agf->agf_flcount, 1);
-       xfs_trans_agflist_delta(tp, 1);
-       pag->pagf_flcount++;
++ifeq ($(CONFIG_XFS_TRACE),y)
++      EXTRA_CFLAGS += -DCONFIG_XFS_TRACE
++endif
++
+ ifeq ($(CONFIG_XFS_DEBUG),y)
+       EXTRA_CFLAGS += -g
++      EXTRA_CFLAGS += -DCONFIG_XFS_DEBUG
+ endif
  
-       logflags = XFS_AGF_FLLAST | XFS_AGF_FLCOUNT;
-       if (btreeblk) {
--              be32_add(&agf->agf_btreeblks, -1);
-+              be32_add_cpu(&agf->agf_btreeblks, -1);
-               pag->pagf_btreeblks--;
-               logflags |= XFS_AGF_BTREEBLKS;
-       }
-diff -Nurd linux-2.6.24/fs/xfs/xfs_alloc_btree.c linux-2.6.24-oxe810/fs/xfs/xfs_alloc_btree.c
---- linux-2.6.24/fs/xfs/xfs_alloc_btree.c      2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/xfs/xfs_alloc_btree.c       2008-06-11 17:46:48.000000000 +0200
+ obj-$(CONFIG_XFS_FS)          += xfs.o
+diff -Nurd linux-2.6.24.4/fs/xfs/xfs_alloc_btree.c linux-2.6.24/fs/xfs/xfs_alloc_btree.c
+--- linux-2.6.24.4/fs/xfs/xfs_alloc_btree.c    2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/xfs/xfs_alloc_btree.c      2010-01-14 14:01:15.000000000 +0100
 @@ -221,7 +221,7 @@
                         */
                        bno = be32_to_cpu(agf->agf_roots[cur->bc_btnum]);
@@ -45751,9 +41300,73 @@ diff -Nurd linux-2.6.24/fs/xfs/xfs_alloc_btree.c linux-2.6.24-oxe810/fs/xfs/xfs_
        right->bb_rightsib = left->bb_rightsib;
        left->bb_rightsib = cpu_to_be32(rbno);
        right->bb_leftsib = cpu_to_be32(lbno);
-diff -Nurd linux-2.6.24/fs/xfs/xfs_attr_leaf.c linux-2.6.24-oxe810/fs/xfs/xfs_attr_leaf.c
---- linux-2.6.24/fs/xfs/xfs_attr_leaf.c        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/xfs/xfs_attr_leaf.c 2008-06-11 17:46:48.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/xfs/xfs_alloc.c linux-2.6.24/fs/xfs/xfs_alloc.c
+--- linux-2.6.24.4/fs/xfs/xfs_alloc.c  2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/xfs/xfs_alloc.c    2010-01-14 14:01:15.000000000 +0100
+@@ -592,7 +592,7 @@
+               if (!(args->wasfromfl)) {
+                       agf = XFS_BUF_TO_AGF(args->agbp);
+-                      be32_add(&agf->agf_freeblks, -(args->len));
++                      be32_add_cpu(&agf->agf_freeblks, -(args->len));
+                       xfs_trans_agblocks_delta(args->tp,
+                                                -((long)(args->len)));
+                       args->pag->pagf_freeblks -= args->len;
+@@ -1720,7 +1720,7 @@
+               agf = XFS_BUF_TO_AGF(agbp);
+               pag = &mp->m_perag[agno];
+-              be32_add(&agf->agf_freeblks, len);
++              be32_add_cpu(&agf->agf_freeblks, len);
+               xfs_trans_agblocks_delta(tp, len);
+               pag->pagf_freeblks += len;
+               XFS_WANT_CORRUPTED_GOTO(
+@@ -2008,18 +2008,18 @@
+        * Get the block number and update the data structures.
+        */
+       bno = be32_to_cpu(agfl->agfl_bno[be32_to_cpu(agf->agf_flfirst)]);
+-      be32_add(&agf->agf_flfirst, 1);
++      be32_add_cpu(&agf->agf_flfirst, 1);
+       xfs_trans_brelse(tp, agflbp);
+       if (be32_to_cpu(agf->agf_flfirst) == XFS_AGFL_SIZE(mp))
+               agf->agf_flfirst = 0;
+       pag = &mp->m_perag[be32_to_cpu(agf->agf_seqno)];
+-      be32_add(&agf->agf_flcount, -1);
++      be32_add_cpu(&agf->agf_flcount, -1);
+       xfs_trans_agflist_delta(tp, -1);
+       pag->pagf_flcount--;
+       logflags = XFS_AGF_FLFIRST | XFS_AGF_FLCOUNT;
+       if (btreeblk) {
+-              be32_add(&agf->agf_btreeblks, 1);
++              be32_add_cpu(&agf->agf_btreeblks, 1);
+               pag->pagf_btreeblks++;
+               logflags |= XFS_AGF_BTREEBLKS;
+       }
+@@ -2117,17 +2117,17 @@
+                       be32_to_cpu(agf->agf_seqno), &agflbp)))
+               return error;
+       agfl = XFS_BUF_TO_AGFL(agflbp);
+-      be32_add(&agf->agf_fllast, 1);
++      be32_add_cpu(&agf->agf_fllast, 1);
+       if (be32_to_cpu(agf->agf_fllast) == XFS_AGFL_SIZE(mp))
+               agf->agf_fllast = 0;
+       pag = &mp->m_perag[be32_to_cpu(agf->agf_seqno)];
+-      be32_add(&agf->agf_flcount, 1);
++      be32_add_cpu(&agf->agf_flcount, 1);
+       xfs_trans_agflist_delta(tp, 1);
+       pag->pagf_flcount++;
+       logflags = XFS_AGF_FLLAST | XFS_AGF_FLCOUNT;
+       if (btreeblk) {
+-              be32_add(&agf->agf_btreeblks, -1);
++              be32_add_cpu(&agf->agf_btreeblks, -1);
+               pag->pagf_btreeblks--;
+               logflags |= XFS_AGF_BTREEBLKS;
+       }
+diff -Nurd linux-2.6.24.4/fs/xfs/xfs_attr_leaf.c linux-2.6.24/fs/xfs/xfs_attr_leaf.c
+--- linux-2.6.24.4/fs/xfs/xfs_attr_leaf.c      2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/xfs/xfs_attr_leaf.c        2010-01-14 14:01:15.000000000 +0100
 @@ -319,7 +319,7 @@
        memcpy(sfe->nameval, args->name, args->namelen);
        memcpy(&sfe->nameval[args->namelen], args->value, args->valuelen);
@@ -45903,9 +41516,9 @@ diff -Nurd linux-2.6.24/fs/xfs/xfs_attr_leaf.c linux-2.6.24-oxe810/fs/xfs/xfs_at
                        sizeof(xfs_attr_leaf_entry_t));
        hdr_d->freemap[0].size = cpu_to_be16(be16_to_cpu(hdr_d->firstused)
                              - be16_to_cpu(hdr_d->freemap[0].base));
-diff -Nurd linux-2.6.24/fs/xfs/xfs_bmap_btree.c linux-2.6.24-oxe810/fs/xfs/xfs_bmap_btree.c
---- linux-2.6.24/fs/xfs/xfs_bmap_btree.c       2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/xfs/xfs_bmap_btree.c        2008-06-11 17:46:48.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/xfs/xfs_bmap_btree.c linux-2.6.24/fs/xfs/xfs_bmap_btree.c
+--- linux-2.6.24.4/fs/xfs/xfs_bmap_btree.c     2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/xfs/xfs_bmap_btree.c       2010-01-14 14:01:15.000000000 +0100
 @@ -631,7 +631,7 @@
                memcpy(lrp, rrp, numrrecs * sizeof(*lrp));
                xfs_bmbt_log_recs(cur, lbp, numlrecs + 1, numlrecs + numrrecs);
@@ -45972,9 +41585,9 @@ diff -Nurd linux-2.6.24/fs/xfs/xfs_bmap_btree.c linux-2.6.24-oxe810/fs/xfs/xfs_b
        block->bb_numrecs = cpu_to_be16(1);
        cur->bc_nlevels++;
        cur->bc_ptrs[level + 1] = 1;
-diff -Nurd linux-2.6.24/fs/xfs/xfs_da_btree.c linux-2.6.24-oxe810/fs/xfs/xfs_da_btree.c
---- linux-2.6.24/fs/xfs/xfs_da_btree.c 2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/xfs/xfs_da_btree.c  2008-06-11 17:46:48.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/xfs/xfs_da_btree.c linux-2.6.24/fs/xfs/xfs_da_btree.c
+--- linux-2.6.24.4/fs/xfs/xfs_da_btree.c       2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/xfs/xfs_da_btree.c 2010-01-14 14:01:15.000000000 +0100
 @@ -511,12 +511,12 @@
                 * Move the req'd B-tree elements from high in node1 to
                 * low in node2.
@@ -46035,9 +41648,9 @@ diff -Nurd linux-2.6.24/fs/xfs/xfs_da_btree.c linux-2.6.24-oxe810/fs/xfs/xfs_da_
  
        xfs_da_log_buf(tp, save_blk->bp,
                XFS_DA_LOGRANGE(save_node, &save_node->hdr,
-diff -Nurd linux-2.6.24/fs/xfs/xfs_dir2_block.c linux-2.6.24-oxe810/fs/xfs/xfs_dir2_block.c
---- linux-2.6.24/fs/xfs/xfs_dir2_block.c       2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/xfs/xfs_dir2_block.c        2008-06-11 17:46:48.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/xfs/xfs_dir2_block.c linux-2.6.24/fs/xfs/xfs_dir2_block.c
+--- linux-2.6.24.4/fs/xfs/xfs_dir2_block.c     2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/xfs/xfs_dir2_block.c       2010-01-14 14:01:15.000000000 +0100
 @@ -271,7 +271,7 @@
                }
                lfloglow = toidx + 1 - (be32_to_cpu(btp->stale) - 1);
@@ -46074,9 +41687,9 @@ diff -Nurd linux-2.6.24/fs/xfs/xfs_dir2_block.c linux-2.6.24-oxe810/fs/xfs/xfs_d
        xfs_dir2_block_log_tail(tp, bp);
        /*
         * Remove the leaf entry by marking it stale.
-diff -Nurd linux-2.6.24/fs/xfs/xfs_dir2_data.c linux-2.6.24-oxe810/fs/xfs/xfs_dir2_data.c
---- linux-2.6.24/fs/xfs/xfs_dir2_data.c        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/xfs/xfs_dir2_data.c 2008-06-11 17:46:48.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/xfs/xfs_dir2_data.c linux-2.6.24/fs/xfs/xfs_dir2_data.c
+--- linux-2.6.24.4/fs/xfs/xfs_dir2_data.c      2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/xfs/xfs_dir2_data.c        2010-01-14 14:01:15.000000000 +0100
 @@ -587,7 +587,7 @@
                /*
                 * Fix up the new big freespace.
@@ -46095,9 +41708,9 @@ diff -Nurd linux-2.6.24/fs/xfs/xfs_dir2_data.c linux-2.6.24-oxe810/fs/xfs/xfs_di
                *xfs_dir2_data_unused_tag_p(prevdup) =
                        cpu_to_be16((char *)prevdup - (char *)d);
                xfs_dir2_data_log_unused(tp, bp, prevdup);
-diff -Nurd linux-2.6.24/fs/xfs/xfs_dir2_leaf.c linux-2.6.24-oxe810/fs/xfs/xfs_dir2_leaf.c
---- linux-2.6.24/fs/xfs/xfs_dir2_leaf.c        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/xfs/xfs_dir2_leaf.c 2008-06-11 17:46:48.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/xfs/xfs_dir2_leaf.c linux-2.6.24/fs/xfs/xfs_dir2_leaf.c
+--- linux-2.6.24.4/fs/xfs/xfs_dir2_leaf.c      2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/xfs/xfs_dir2_leaf.c        2010-01-14 14:01:15.000000000 +0100
 @@ -359,7 +359,7 @@
                        bestsp--;
                        memmove(&bestsp[0], &bestsp[1],
@@ -46170,9 +41783,9 @@ diff -Nurd linux-2.6.24/fs/xfs/xfs_dir2_leaf.c linux-2.6.24-oxe810/fs/xfs/xfs_di
        memmove(&bestsp[1], &bestsp[0], be32_to_cpu(ltp->bestcount) * sizeof(*bestsp));
        xfs_dir2_leaf_log_tail(tp, lbp);
        xfs_dir2_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1);
-diff -Nurd linux-2.6.24/fs/xfs/xfs_dir2_node.c linux-2.6.24-oxe810/fs/xfs/xfs_dir2_node.c
---- linux-2.6.24/fs/xfs/xfs_dir2_node.c        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/xfs/xfs_dir2_node.c 2008-06-11 17:46:48.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/xfs/xfs_dir2_node.c linux-2.6.24/fs/xfs/xfs_dir2_node.c
+--- linux-2.6.24.4/fs/xfs/xfs_dir2_node.c      2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/xfs/xfs_dir2_node.c        2010-01-14 14:01:15.000000000 +0100
 @@ -254,7 +254,7 @@
                                (be16_to_cpu(leaf->hdr.count) - index) * sizeof(*lep));
                lfloglow = index;
@@ -46233,9 +41846,9 @@ diff -Nurd linux-2.6.24/fs/xfs/xfs_dir2_node.c linux-2.6.24-oxe810/fs/xfs/xfs_di
                        xfs_dir2_free_log_header(tp, fbp);
                }
                /*
-diff -Nurd linux-2.6.24/fs/xfs/xfs_fsops.c linux-2.6.24-oxe810/fs/xfs/xfs_fsops.c
---- linux-2.6.24/fs/xfs/xfs_fsops.c    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/xfs/xfs_fsops.c     2008-06-11 17:46:48.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/xfs/xfs_fsops.c linux-2.6.24/fs/xfs/xfs_fsops.c
+--- linux-2.6.24.4/fs/xfs/xfs_fsops.c  2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/xfs/xfs_fsops.c    2010-01-14 14:01:15.000000000 +0100
 @@ -318,7 +318,7 @@
                }
                ASSERT(bp);
@@ -46254,52 +41867,9 @@ diff -Nurd linux-2.6.24/fs/xfs/xfs_fsops.c linux-2.6.24-oxe810/fs/xfs/xfs_fsops.
                ASSERT(be32_to_cpu(agf->agf_length) ==
                       be32_to_cpu(agi->agi_length));
                xfs_alloc_log_agf(tp, bp, XFS_AGF_LENGTH);
-diff -Nurd linux-2.6.24/fs/xfs/xfs_ialloc.c linux-2.6.24-oxe810/fs/xfs/xfs_ialloc.c
---- linux-2.6.24/fs/xfs/xfs_ialloc.c   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/xfs/xfs_ialloc.c    2008-06-11 17:46:48.000000000 +0200
-@@ -301,8 +301,8 @@
-               }
-               xfs_trans_inode_alloc_buf(tp, fbuf);
-       }
--      be32_add(&agi->agi_count, newlen);
--      be32_add(&agi->agi_freecount, newlen);
-+      be32_add_cpu(&agi->agi_count, newlen);
-+      be32_add_cpu(&agi->agi_freecount, newlen);
-       agno = be32_to_cpu(agi->agi_seqno);
-       down_read(&args.mp->m_peraglock);
-       args.mp->m_perag[agno].pagi_freecount += newlen;
-@@ -885,7 +885,7 @@
-       if ((error = xfs_inobt_update(cur, rec.ir_startino, rec.ir_freecount,
-                       rec.ir_free)))
-               goto error0;
--      be32_add(&agi->agi_freecount, -1);
-+      be32_add_cpu(&agi->agi_freecount, -1);
-       xfs_ialloc_log_agi(tp, agbp, XFS_AGI_FREECOUNT);
-       down_read(&mp->m_peraglock);
-       mp->m_perag[tagno].pagi_freecount--;
-@@ -1065,8 +1065,8 @@
-                * to be freed when the transaction is committed.
-                */
-               ilen = XFS_IALLOC_INODES(mp);
--              be32_add(&agi->agi_count, -ilen);
--              be32_add(&agi->agi_freecount, -(ilen - 1));
-+              be32_add_cpu(&agi->agi_count, -ilen);
-+              be32_add_cpu(&agi->agi_freecount, -(ilen - 1));
-               xfs_ialloc_log_agi(tp, agbp, XFS_AGI_COUNT | XFS_AGI_FREECOUNT);
-               down_read(&mp->m_peraglock);
-               mp->m_perag[agno].pagi_freecount -= ilen - 1;
-@@ -1095,7 +1095,7 @@
-               /* 
-                * Change the inode free counts and log the ag/sb changes.
-                */
--              be32_add(&agi->agi_freecount, 1);
-+              be32_add_cpu(&agi->agi_freecount, 1);
-               xfs_ialloc_log_agi(tp, agbp, XFS_AGI_FREECOUNT);
-               down_read(&mp->m_peraglock);
-               mp->m_perag[agno].pagi_freecount++;
-diff -Nurd linux-2.6.24/fs/xfs/xfs_ialloc_btree.c linux-2.6.24-oxe810/fs/xfs/xfs_ialloc_btree.c
---- linux-2.6.24/fs/xfs/xfs_ialloc_btree.c     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/xfs/xfs_ialloc_btree.c      2008-06-11 17:46:48.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/xfs/xfs_ialloc_btree.c linux-2.6.24/fs/xfs/xfs_ialloc_btree.c
+--- linux-2.6.24.4/fs/xfs/xfs_ialloc_btree.c   2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/xfs/xfs_ialloc_btree.c     2010-01-14 14:01:15.000000000 +0100
 @@ -189,7 +189,7 @@
                         */
                        bno = be32_to_cpu(agi->agi_root);
@@ -46366,9 +41936,52 @@ diff -Nurd linux-2.6.24/fs/xfs/xfs_ialloc_btree.c linux-2.6.24-oxe810/fs/xfs/xfs
        right->bb_rightsib = left->bb_rightsib;
        left->bb_rightsib = cpu_to_be32(args.agbno);
        right->bb_leftsib = cpu_to_be32(lbno);
-diff -Nurd linux-2.6.24/fs/xfs/xfs_inode.c linux-2.6.24-oxe810/fs/xfs/xfs_inode.c
---- linux-2.6.24/fs/xfs/xfs_inode.c    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/xfs/xfs_inode.c     2008-06-11 17:46:48.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/xfs/xfs_ialloc.c linux-2.6.24/fs/xfs/xfs_ialloc.c
+--- linux-2.6.24.4/fs/xfs/xfs_ialloc.c 2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/xfs/xfs_ialloc.c   2010-01-14 14:01:15.000000000 +0100
+@@ -301,8 +301,8 @@
+               }
+               xfs_trans_inode_alloc_buf(tp, fbuf);
+       }
+-      be32_add(&agi->agi_count, newlen);
+-      be32_add(&agi->agi_freecount, newlen);
++      be32_add_cpu(&agi->agi_count, newlen);
++      be32_add_cpu(&agi->agi_freecount, newlen);
+       agno = be32_to_cpu(agi->agi_seqno);
+       down_read(&args.mp->m_peraglock);
+       args.mp->m_perag[agno].pagi_freecount += newlen;
+@@ -885,7 +885,7 @@
+       if ((error = xfs_inobt_update(cur, rec.ir_startino, rec.ir_freecount,
+                       rec.ir_free)))
+               goto error0;
+-      be32_add(&agi->agi_freecount, -1);
++      be32_add_cpu(&agi->agi_freecount, -1);
+       xfs_ialloc_log_agi(tp, agbp, XFS_AGI_FREECOUNT);
+       down_read(&mp->m_peraglock);
+       mp->m_perag[tagno].pagi_freecount--;
+@@ -1065,8 +1065,8 @@
+                * to be freed when the transaction is committed.
+                */
+               ilen = XFS_IALLOC_INODES(mp);
+-              be32_add(&agi->agi_count, -ilen);
+-              be32_add(&agi->agi_freecount, -(ilen - 1));
++              be32_add_cpu(&agi->agi_count, -ilen);
++              be32_add_cpu(&agi->agi_freecount, -(ilen - 1));
+               xfs_ialloc_log_agi(tp, agbp, XFS_AGI_COUNT | XFS_AGI_FREECOUNT);
+               down_read(&mp->m_peraglock);
+               mp->m_perag[agno].pagi_freecount -= ilen - 1;
+@@ -1095,7 +1095,7 @@
+               /* 
+                * Change the inode free counts and log the ag/sb changes.
+                */
+-              be32_add(&agi->agi_freecount, 1);
++              be32_add_cpu(&agi->agi_freecount, 1);
+               xfs_ialloc_log_agi(tp, agbp, XFS_AGI_FREECOUNT);
+               down_read(&mp->m_peraglock);
+               mp->m_perag[agno].pagi_freecount++;
+diff -Nurd linux-2.6.24.4/fs/xfs/xfs_inode.c linux-2.6.24/fs/xfs/xfs_inode.c
+--- linux-2.6.24.4/fs/xfs/xfs_inode.c  2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/xfs/xfs_inode.c    2010-01-14 14:01:15.000000000 +0100
 @@ -1158,6 +1158,16 @@
        if ((prid != 0) && (ip->i_d.di_version == XFS_DINODE_VERSION_1))
                xfs_bump_ino_vers2(tp, ip);
@@ -46386,9 +41999,9 @@ diff -Nurd linux-2.6.24/fs/xfs/xfs_inode.c linux-2.6.24-oxe810/fs/xfs/xfs_inode.
        if (pip && XFS_INHERIT_GID(pip)) {
                ip->i_d.di_gid = pip->i_d.di_gid;
                if ((pip->i_d.di_mode & S_ISGID) && (mode & S_IFMT) == S_IFDIR) {
-diff -Nurd linux-2.6.24/fs/xfs/xfs_inode.h linux-2.6.24-oxe810/fs/xfs/xfs_inode.h
---- linux-2.6.24/fs/xfs/xfs_inode.h    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/xfs/xfs_inode.h     2008-06-11 17:46:48.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/xfs/xfs_inode.h linux-2.6.24/fs/xfs/xfs_inode.h
+--- linux-2.6.24.4/fs/xfs/xfs_inode.h  2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/xfs/xfs_inode.h    2010-01-14 14:01:15.000000000 +0100
 @@ -495,6 +495,11 @@
  #define XFS_INHERIT_GID(pip)  \
        (((pip)->i_mount->m_flags & XFS_MOUNT_GRPID) || \
@@ -46401,9 +42014,9 @@ diff -Nurd linux-2.6.24/fs/xfs/xfs_inode.h linux-2.6.24-oxe810/fs/xfs/xfs_inode.
  
  /*
   * Flags for xfs_iget()
-diff -Nurd linux-2.6.24/fs/xfs/xfs_log.c linux-2.6.24-oxe810/fs/xfs/xfs_log.c
---- linux-2.6.24/fs/xfs/xfs_log.c      2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/xfs/xfs_log.c       2008-06-11 17:46:48.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/xfs/xfs_log.c linux-2.6.24/fs/xfs/xfs_log.c
+--- linux-2.6.24.4/fs/xfs/xfs_log.c    2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/xfs/xfs_log.c      2010-01-14 14:01:15.000000000 +0100
 @@ -399,10 +399,10 @@
  {
        xlog_t *log = mp->m_log;
@@ -47722,9 +43335,9 @@ diff -Nurd linux-2.6.24/fs/xfs/xfs_log.c linux-2.6.24-oxe810/fs/xfs/xfs_log.c
        }
  #endif
        /* return non-zero if log IOERROR transition had already happened */
-diff -Nurd linux-2.6.24/fs/xfs/xfs_log.h linux-2.6.24-oxe810/fs/xfs/xfs_log.h
---- linux-2.6.24/fs/xfs/xfs_log.h      2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/xfs/xfs_log.h       2008-06-11 17:46:48.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/xfs/xfs_log.h linux-2.6.24/fs/xfs/xfs_log.h
+--- linux-2.6.24.4/fs/xfs/xfs_log.h    2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/xfs/xfs_log.h      2010-01-14 14:01:15.000000000 +0100
 @@ -23,7 +23,7 @@
  #define CYCLE_LSN(lsn) ((uint)((lsn)>>32))
  #define BLOCK_LSN(lsn) ((uint)(lsn))
@@ -47734,9 +43347,9 @@ diff -Nurd linux-2.6.24/fs/xfs/xfs_log.h linux-2.6.24-oxe810/fs/xfs/xfs_log.h
  
  #ifdef __KERNEL__
  /*
-diff -Nurd linux-2.6.24/fs/xfs/xfs_log_priv.h linux-2.6.24-oxe810/fs/xfs/xfs_log_priv.h
---- linux-2.6.24/fs/xfs/xfs_log_priv.h 2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/xfs/xfs_log_priv.h  2008-06-11 17:46:48.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/xfs/xfs_log_priv.h linux-2.6.24/fs/xfs/xfs_log_priv.h
+--- linux-2.6.24.4/fs/xfs/xfs_log_priv.h       2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/xfs/xfs_log_priv.h 2010-01-14 14:01:15.000000000 +0100
 @@ -55,29 +55,19 @@
        BTOBB(XLOG_MAX_ICLOGS << (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb) ? \
         XLOG_MAX_RECORD_BSHIFT : XLOG_BIG_RECORD_BSHIFT))
@@ -47877,9 +43490,9 @@ diff -Nurd linux-2.6.24/fs/xfs/xfs_log_priv.h linux-2.6.24-oxe810/fs/xfs/xfs_log
  extern int     xlog_recover(xlog_t *log);
  extern int     xlog_recover_finish(xlog_t *log, int mfsi_flags);
  extern void    xlog_pack_data(xlog_t *log, xlog_in_core_t *iclog, int);
-diff -Nurd linux-2.6.24/fs/xfs/xfs_log_recover.c linux-2.6.24-oxe810/fs/xfs/xfs_log_recover.c
---- linux-2.6.24/fs/xfs/xfs_log_recover.c      2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/xfs/xfs_log_recover.c       2008-06-11 17:46:48.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/xfs/xfs_log_recover.c linux-2.6.24/fs/xfs/xfs_log_recover.c
+--- linux-2.6.24.4/fs/xfs/xfs_log_recover.c    2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/xfs/xfs_log_recover.c      2010-01-14 14:01:15.000000000 +0100
 @@ -198,7 +198,7 @@
        cmn_err(CE_DEBUG, "    log : uuid = ");
        for (b = 0; b < 16; b++)
@@ -48471,9 +44084,9 @@ diff -Nurd linux-2.6.24/fs/xfs/xfs_log_recover.c linux-2.6.24-oxe810/fs/xfs/xfs_
  
        if (tail_blk != head_blk) {
                /* There used to be a comment here:
-diff -Nurd linux-2.6.24/fs/xfs/xfs_trans.c linux-2.6.24-oxe810/fs/xfs/xfs_trans.c
---- linux-2.6.24/fs/xfs/xfs_trans.c    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/xfs/xfs_trans.c     2008-06-11 17:46:48.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/xfs/xfs_trans.c linux-2.6.24/fs/xfs/xfs_trans.c
+--- linux-2.6.24.4/fs/xfs/xfs_trans.c  2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/xfs/xfs_trans.c    2010-01-14 14:01:15.000000000 +0100
 @@ -567,26 +567,26 @@
         */
        if (!xfs_sb_version_haslazysbcount(&(tp->t_mountp->m_sb))) {
@@ -48533,9 +44146,9 @@ diff -Nurd linux-2.6.24/fs/xfs/xfs_trans.c linux-2.6.24-oxe810/fs/xfs/xfs_trans.
                whole = 1;
        }
        if (tp->t_rextslog_delta) {
-diff -Nurd linux-2.6.24/fs/xfs/xfs_vnodeops.c linux-2.6.24-oxe810/fs/xfs/xfs_vnodeops.c
---- linux-2.6.24/fs/xfs/xfs_vnodeops.c 2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/fs/xfs/xfs_vnodeops.c  2008-06-11 17:46:48.000000000 +0200
+diff -Nurd linux-2.6.24.4/fs/xfs/xfs_vnodeops.c linux-2.6.24/fs/xfs/xfs_vnodeops.c
+--- linux-2.6.24.4/fs/xfs/xfs_vnodeops.c       2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/fs/xfs/xfs_vnodeops.c 2010-01-14 14:01:15.000000000 +0100
 @@ -3558,11 +3558,11 @@
                if (iip && iip->ili_last_lsn) {
                        xlog_t          *log = mp->m_log;
@@ -48551,104 +44164,9 @@ diff -Nurd linux-2.6.24/fs/xfs/xfs_vnodeops.c linux-2.6.24-oxe810/fs/xfs/xfs_vno
  
                        if ((XFS_LSN_CMP(iip->ili_last_lsn, sync_lsn) > 0)) {
                                if (flags & FLUSH_SYNC)
-diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/GPIO_PST_FunctionEnables.inc linux-2.6.24-oxe810/include/asm-arm/arch-hipox/GPIO_PST_FunctionEnables.inc
---- linux-2.6.24/include/asm-arm/arch-hipox/GPIO_PST_FunctionEnables.inc       1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/include/asm-arm/arch-hipox/GPIO_PST_FunctionEnables.inc        2008-06-11 17:45:12.000000000 +0200
-@@ -0,0 +1,91 @@
-+/**
-+ * -- GPIO Function Enable Mappings --
-+ * Auto Generated by asic/chips/nas/root.user/docs/specs/map2CInlude
-+ */
-+// GPIO Primary Function Enables
-+#define  PRIMARY_FUNCTION_ENABLE_SYSPCI_GNT_N0          (0) //  As Output
-+#define  PRIMARY_FUNCTION_ENABLE_SYSPCI_GNT_N1          (1) //  As Output
-+#define  PRIMARY_FUNCTION_ENABLE_SYSPCI_GNT_N2          (2) //  As Output
-+#define  PRIMARY_FUNCTION_ENABLE_SYSPCI_GNT_N3          (3) //  As Output
-+#define  PRIMARY_FUNCTION_ENABLE_SYSPCI_REQ_N0          (4) //  As Input
-+#define  PRIMARY_FUNCTION_ENABLE_SYSPCI_REQ_N1          (5) //  As Input
-+#define  PRIMARY_FUNCTION_ENABLE_SYSPCI_REQ_N2          (6) //  As Input
-+#define  PRIMARY_FUNCTION_ENABLE_SYSPCI_REQ_N3          (7) //  As Input
-+#define  PRIMARY_FUNCTION_ENABLE_PCI_CKO                (8) //  As Output
-+#define  PRIMARY_FUNCTION_ENABLE_STATIC_OE_N            (12) //  As Output
-+#define  PRIMARY_FUNCTION_ENABLE_STATIC_ADDR21          (13) //  As Output
-+#define  PRIMARY_FUNCTION_ENABLE_STATIC_ADDR20          (14) //  As Output
-+#define  PRIMARY_FUNCTION_ENABLE_STATIC_ADDR19          (15) //  As Output
-+#define  PRIMARY_FUNCTION_ENABLE_STATIC_ADDR18          (16) //  As Output
-+#define  PRIMARY_FUNCTION_ENABLE_STATIC_ADDR17          (17) //  As Output
-+#define  PRIMARY_FUNCTION_ENABLE_STATIC_ADDR16          (18) //  As Output
-+#define  PRIMARY_FUNCTION_ENABLE_STATIC_CS_N0           (19) //  As Output
-+#define  PRIMARY_FUNCTION_ENABLE_STATIC_CS_N1           (20) //  As Output
-+#define  PRIMARY_FUNCTION_ENABLE_STATIC_WE_N0           (21) //  As Output
-+#define  PRIMARY_FUNCTION_ENABLE_STATIC_WE_N1           (22) //  As Output
-+#define  PRIMARY_FUNCTION_ENABLE_USBA_PWRO              (23) //  As Output
-+#define  PRIMARY_FUNCTION_ENABLE_USBA_OVERI             (24) //  As Input
-+#define  PRIMARY_FUNCTION_ENABLE_USBB_PWRO              (25) //  As Output
-+#define  PRIMARY_FUNCTION_ENABLE_USBB_OVERI             (26) //  As Input
-+#define  PRIMARY_FUNCTION_ENABLE_USBC_PWRO              (27) //  As Output
-+#define  PRIMARY_FUNCTION_ENABLE_USBC_OVERI             (28) //  As Input
-+#define  PRIMARY_FUNCTION_ENABLE_FAN_TEMP               (29) //  Is Bidirectional
-+#define  PRIMARY_FUNCTION_ENABLE_FAN_TACHO              (30) //  As Input
-+#define  PRIMARY_FUNCTION_ENABLE_FAN_PWM0               (31) //  As Output
-+#define  PRIMARY_FUNCTION_ENABLE_FAN_PWM1               (32) //  As Output
-+#define  PRIMARY_FUNCTION_ENABLE_IBIW_D                 (33) //  Is Bidirectional
-+#define  PRIMARY_FUNCTION_ENABLE_IBIW_LED               (34) //  As Output
-+// GPIO Secondary Function Enables
-+#define  SECONDARY_FUNCTION_ENABLE_SYSPCI_REQ_OUT_N       (0) //  As Output
-+#define  SECONDARY_FUNCTION_ENABLE_SYSPCI_GNT_IN_N        (1) //  As Input
-+#define  SECONDARY_FUNCTION_ENABLE_PCI_IDSEL              (2) //  As Input
-+#define  SECONDARY_FUNCTION_ENABLE_IRRX_IN                (3) //  As Input
-+#define  SECONDARY_FUNCTION_ENABLE_FAN_PWM3               (5) //  As Output
-+#define  SECONDARY_FUNCTION_ENABLE_AUDIO_TX_BITCK         (6) //  As Input
-+#define  SECONDARY_FUNCTION_ENABLE_AUDIO_TXLRCK           (7) //  As Input
-+#define  SECONDARY_FUNCTION_ENABLE_FAN_PWM2               (8) //  As Output
-+#define  SECONDARY_FUNCTION_ENABLE_USB_CKO                (10) //  As Output
-+#define  SECONDARY_FUNCTION_ENABLE_PCI_CCLKRUN_N          (12) //  Is Bidirectional
-+#define  SECONDARY_FUNCTION_ENABLE_PCI_LOCK_N             (13) //  As Input
-+#define  SECONDARY_FUNCTION_ENABLE_PCI_PERR_N             (14) //  Is Bidirectional
-+#define  SECONDARY_FUNCTION_ENABLE_PCI_SERR_N             (15) //  As Output
-+#define  SECONDARY_FUNCTION_ENABLE_MEM_DLLTGL             (16) //  As Output
-+#define  SECONDARY_FUNCTION_ENABLE_SATA_OBS_RBC0          (17) //  As Output
-+#define  SECONDARY_FUNCTION_ENABLE_PCI_CINT_N             (18) //  As Output
-+#define  SECONDARY_FUNCTION_ENABLE_PCI_CSTSCHG_N          (19) //  As Output
-+#define  SECONDARY_FUNCTION_ENABLE_PCI_CKO                (23) //  As Output
-+#define  SECONDARY_FUNCTION_ENABLE_AUDIO_TXD0             (25) //  As Output
-+#define  SECONDARY_FUNCTION_ENABLE_AUDIO_RXD0             (26) //  As Input
-+#define  SECONDARY_FUNCTION_ENABLE_AUDIO_RXLRCK           (27) //  As Input
-+#define  SECONDARY_FUNCTION_ENABLE_AUDIO_RX_BITCK         (28) //  As Input
-+#define  SECONDARY_FUNCTION_ENABLE_AUDIO_TXD2             (29) //  As Output
-+#define  SECONDARY_FUNCTION_ENABLE_AUDIO_RXD2             (30) //  As Input
-+#define  SECONDARY_FUNCTION_ENABLE_AUDIO_TXD3             (31) //  As Output
-+#define  SECONDARY_FUNCTION_ENABLE_AUDIO_RXD3             (32) //  As Input
-+#define  SECONDARY_FUNCTION_ENABLE_AUDIO_RXD1             (33) //  As Input
-+#define  SECONDARY_FUNCTION_ENABLE_AUDIO_TXD1             (34) //  As Output
-+// GPIO Tertiary Function Enables
-+#define  TERTIARY_FUNCTION_ENABLE_UART3_RI_N             (0) //  As Input
-+#define  TERTIARY_FUNCTION_ENABLE_UART3_CD_N             (1) //  As Input
-+#define  TERTIARY_FUNCTION_ENABLE_UART3_CTS_N            (2) //  As Input
-+#define  TERTIARY_FUNCTION_ENABLE_UART3_DSR_N            (3) //  As Input
-+#define  TERTIARY_FUNCTION_ENABLE_UART3_DTR_N            (4) //  As Output
-+#define  TERTIARY_FUNCTION_ENABLE_UART3_RTS_N            (5) //  As Output
-+#define  TERTIARY_FUNCTION_ENABLE_UART3_SIN              (6) //  As Input
-+#define  TERTIARY_FUNCTION_ENABLE_UART3_SOUT             (7) //  As Output
-+#define  TERTIARY_FUNCTION_ENABLE_UART2_DSR_N            (8) //  As Input
-+#define  TERTIARY_FUNCTION_ENABLE_UART2_RTS_N            (9) //  As Output
-+#define  TERTIARY_FUNCTION_ENABLE_UART2_SOUT             (20) //  As Output
-+#define  TERTIARY_FUNCTION_ENABLE_UART2_SIN              (22) //  As Input
-+#define  TERTIARY_FUNCTION_ENABLE_UART2_RI_N             (23) //  As Input
-+#define  TERTIARY_FUNCTION_ENABLE_UART2_CD_N             (24) //  As Input
-+#define  TERTIARY_FUNCTION_ENABLE_UART2_DTR_N            (25) //  As Output
-+#define  TERTIARY_FUNCTION_ENABLE_UART2_CTS_N            (26) //  As Input
-+#define  TERTIARY_FUNCTION_ENABLE_UART1_RTS_N            (27) //  As Output
-+#define  TERTIARY_FUNCTION_ENABLE_UART1_CTS_N            (28) //  As Input
-+#define  TERTIARY_FUNCTION_ENABLE_UART1_DSR_N            (29) //  As Input
-+#define  TERTIARY_FUNCTION_ENABLE_UART1_CD_N             (30) //  As Input
-+#define  TERTIARY_FUNCTION_ENABLE_UART1_SOUT             (31) //  As Output
-+#define  TERTIARY_FUNCTION_ENABLE_UART1_SIN              (32) //  As Input
-+#define  TERTIARY_FUNCTION_ENABLE_UART1_RI_N             (33) //  As Input
-+#define  TERTIARY_FUNCTION_ENABLE_UART1_DTR_N            (34) //  As Output
-diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/ahb_mon.h linux-2.6.24-oxe810/include/asm-arm/arch-hipox/ahb_mon.h
---- linux-2.6.24/include/asm-arm/arch-hipox/ahb_mon.h  1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/include/asm-arm/arch-hipox/ahb_mon.h   2008-06-11 17:45:12.000000000 +0200
+diff -Nurd linux-2.6.24.4/include/asm-arm/arch-hipox/ahb_mon.h linux-2.6.24/include/asm-arm/arch-hipox/ahb_mon.h
+--- linux-2.6.24.4/include/asm-arm/arch-hipox/ahb_mon.h        1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/include/asm-arm/arch-hipox/ahb_mon.h  2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,27 @@
 +/* linux/include/asm-arm/arch-hipox/ahb_mon.h
 + *
@@ -48677,9 +44195,9 @@ diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/ahb_mon.h linux-2.6.24-oxe810
 +#endif        //  #if !defined(__AHB_MON_H__)
 +#endif // CONFIG_HIPOX_AHB_MON
 +
-diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/cipher.h linux-2.6.24-oxe810/include/asm-arm/arch-hipox/cipher.h
---- linux-2.6.24/include/asm-arm/arch-hipox/cipher.h   1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/include/asm-arm/arch-hipox/cipher.h    2008-06-11 17:45:12.000000000 +0200
+diff -Nurd linux-2.6.24.4/include/asm-arm/arch-hipox/cipher.h linux-2.6.24/include/asm-arm/arch-hipox/cipher.h
+--- linux-2.6.24.4/include/asm-arm/arch-hipox/cipher.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/include/asm-arm/arch-hipox/cipher.h   2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,139 @@
 +/*
 + * linux/include/asm-arm/arch-hipox/cipher.h
@@ -48820,9 +44338,9 @@ diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/cipher.h linux-2.6.24-oxe810/
 +                            u8 tweak_key[]);
 +
 +#endif
-diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/debug-macro.S linux-2.6.24-oxe810/include/asm-arm/arch-hipox/debug-macro.S
---- linux-2.6.24/include/asm-arm/arch-hipox/debug-macro.S      1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/include/asm-arm/arch-hipox/debug-macro.S       2008-06-11 17:45:12.000000000 +0200
+diff -Nurd linux-2.6.24.4/include/asm-arm/arch-hipox/debug-macro.S linux-2.6.24/include/asm-arm/arch-hipox/debug-macro.S
+--- linux-2.6.24.4/include/asm-arm/arch-hipox/debug-macro.S    1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/include/asm-arm/arch-hipox/debug-macro.S      2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,47 @@
 +/* linux/include/asm-arm/arch-hipox/debug-macro.S
 + *
@@ -48871,9 +44389,9 @@ diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/debug-macro.S linux-2.6.24-ox
 +#             beq             1001b
 +              .endm
 +
-diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/desc_alloc.h linux-2.6.24-oxe810/include/asm-arm/arch-hipox/desc_alloc.h
---- linux-2.6.24/include/asm-arm/arch-hipox/desc_alloc.h       1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/include/asm-arm/arch-hipox/desc_alloc.h        2008-06-11 17:45:12.000000000 +0200
+diff -Nurd linux-2.6.24.4/include/asm-arm/arch-hipox/desc_alloc.h linux-2.6.24/include/asm-arm/arch-hipox/desc_alloc.h
+--- linux-2.6.24.4/include/asm-arm/arch-hipox/desc_alloc.h     1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/include/asm-arm/arch-hipox/desc_alloc.h       2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,62 @@
 +/*
 + * linux/include/asm-arm/arch-hipox/dma.h
@@ -48937,9 +44455,9 @@ diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/desc_alloc.h linux-2.6.24-oxe
 +
 +#endif        //  #if !defined(__DESC_ALLOC_H__)
 +
-diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/dma.h linux-2.6.24-oxe810/include/asm-arm/arch-hipox/dma.h
---- linux-2.6.24/include/asm-arm/arch-hipox/dma.h      1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/include/asm-arm/arch-hipox/dma.h       2008-06-11 17:45:12.000000000 +0200
+diff -Nurd linux-2.6.24.4/include/asm-arm/arch-hipox/dma.h linux-2.6.24/include/asm-arm/arch-hipox/dma.h
+--- linux-2.6.24.4/include/asm-arm/arch-hipox/dma.h    1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/include/asm-arm/arch-hipox/dma.h      2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,299 @@
 +/*
 + * linux/include/asm-arm/arch-hipox/dma.h
@@ -49240,9 +44758,9 @@ diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/dma.h linux-2.6.24-oxe810/inc
 +
 +extern void hipox_dma_free_sg_entries(hipox_dma_sg_entry_t* entries);
 +#endif // __ASM_ARCH_DMA_H
-diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/entry-macro.S linux-2.6.24-oxe810/include/asm-arm/arch-hipox/entry-macro.S
---- linux-2.6.24/include/asm-arm/arch-hipox/entry-macro.S      1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/include/asm-arm/arch-hipox/entry-macro.S       2008-06-11 17:45:12.000000000 +0200
+diff -Nurd linux-2.6.24.4/include/asm-arm/arch-hipox/entry-macro.S linux-2.6.24/include/asm-arm/arch-hipox/entry-macro.S
+--- linux-2.6.24.4/include/asm-arm/arch-hipox/entry-macro.S    1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/include/asm-arm/arch-hipox/entry-macro.S      2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,40 @@
 +/*
 + * include/asm-arm/arch-hipox/entry-macro.S
@@ -49284,9 +44802,104 @@ diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/entry-macro.S linux-2.6.24-ox
 +              .macro  irq_prio_table
 +              .endm
 +
-diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/hardware.h linux-2.6.24-oxe810/include/asm-arm/arch-hipox/hardware.h
---- linux-2.6.24/include/asm-arm/arch-hipox/hardware.h 1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/include/asm-arm/arch-hipox/hardware.h  2008-06-11 17:45:12.000000000 +0200
+diff -Nurd linux-2.6.24.4/include/asm-arm/arch-hipox/GPIO_PST_FunctionEnables.inc linux-2.6.24/include/asm-arm/arch-hipox/GPIO_PST_FunctionEnables.inc
+--- linux-2.6.24.4/include/asm-arm/arch-hipox/GPIO_PST_FunctionEnables.inc     1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/include/asm-arm/arch-hipox/GPIO_PST_FunctionEnables.inc       2010-01-14 14:01:15.000000000 +0100
+@@ -0,0 +1,91 @@
++/**
++ * -- GPIO Function Enable Mappings --
++ * Auto Generated by asic/chips/nas/root.user/docs/specs/map2CInlude
++ */
++// GPIO Primary Function Enables
++#define  PRIMARY_FUNCTION_ENABLE_SYSPCI_GNT_N0          (0) //  As Output
++#define  PRIMARY_FUNCTION_ENABLE_SYSPCI_GNT_N1          (1) //  As Output
++#define  PRIMARY_FUNCTION_ENABLE_SYSPCI_GNT_N2          (2) //  As Output
++#define  PRIMARY_FUNCTION_ENABLE_SYSPCI_GNT_N3          (3) //  As Output
++#define  PRIMARY_FUNCTION_ENABLE_SYSPCI_REQ_N0          (4) //  As Input
++#define  PRIMARY_FUNCTION_ENABLE_SYSPCI_REQ_N1          (5) //  As Input
++#define  PRIMARY_FUNCTION_ENABLE_SYSPCI_REQ_N2          (6) //  As Input
++#define  PRIMARY_FUNCTION_ENABLE_SYSPCI_REQ_N3          (7) //  As Input
++#define  PRIMARY_FUNCTION_ENABLE_PCI_CKO                (8) //  As Output
++#define  PRIMARY_FUNCTION_ENABLE_STATIC_OE_N            (12) //  As Output
++#define  PRIMARY_FUNCTION_ENABLE_STATIC_ADDR21          (13) //  As Output
++#define  PRIMARY_FUNCTION_ENABLE_STATIC_ADDR20          (14) //  As Output
++#define  PRIMARY_FUNCTION_ENABLE_STATIC_ADDR19          (15) //  As Output
++#define  PRIMARY_FUNCTION_ENABLE_STATIC_ADDR18          (16) //  As Output
++#define  PRIMARY_FUNCTION_ENABLE_STATIC_ADDR17          (17) //  As Output
++#define  PRIMARY_FUNCTION_ENABLE_STATIC_ADDR16          (18) //  As Output
++#define  PRIMARY_FUNCTION_ENABLE_STATIC_CS_N0           (19) //  As Output
++#define  PRIMARY_FUNCTION_ENABLE_STATIC_CS_N1           (20) //  As Output
++#define  PRIMARY_FUNCTION_ENABLE_STATIC_WE_N0           (21) //  As Output
++#define  PRIMARY_FUNCTION_ENABLE_STATIC_WE_N1           (22) //  As Output
++#define  PRIMARY_FUNCTION_ENABLE_USBA_PWRO              (23) //  As Output
++#define  PRIMARY_FUNCTION_ENABLE_USBA_OVERI             (24) //  As Input
++#define  PRIMARY_FUNCTION_ENABLE_USBB_PWRO              (25) //  As Output
++#define  PRIMARY_FUNCTION_ENABLE_USBB_OVERI             (26) //  As Input
++#define  PRIMARY_FUNCTION_ENABLE_USBC_PWRO              (27) //  As Output
++#define  PRIMARY_FUNCTION_ENABLE_USBC_OVERI             (28) //  As Input
++#define  PRIMARY_FUNCTION_ENABLE_FAN_TEMP               (29) //  Is Bidirectional
++#define  PRIMARY_FUNCTION_ENABLE_FAN_TACHO              (30) //  As Input
++#define  PRIMARY_FUNCTION_ENABLE_FAN_PWM0               (31) //  As Output
++#define  PRIMARY_FUNCTION_ENABLE_FAN_PWM1               (32) //  As Output
++#define  PRIMARY_FUNCTION_ENABLE_IBIW_D                 (33) //  Is Bidirectional
++#define  PRIMARY_FUNCTION_ENABLE_IBIW_LED               (34) //  As Output
++// GPIO Secondary Function Enables
++#define  SECONDARY_FUNCTION_ENABLE_SYSPCI_REQ_OUT_N       (0) //  As Output
++#define  SECONDARY_FUNCTION_ENABLE_SYSPCI_GNT_IN_N        (1) //  As Input
++#define  SECONDARY_FUNCTION_ENABLE_PCI_IDSEL              (2) //  As Input
++#define  SECONDARY_FUNCTION_ENABLE_IRRX_IN                (3) //  As Input
++#define  SECONDARY_FUNCTION_ENABLE_FAN_PWM3               (5) //  As Output
++#define  SECONDARY_FUNCTION_ENABLE_AUDIO_TX_BITCK         (6) //  As Input
++#define  SECONDARY_FUNCTION_ENABLE_AUDIO_TXLRCK           (7) //  As Input
++#define  SECONDARY_FUNCTION_ENABLE_FAN_PWM2               (8) //  As Output
++#define  SECONDARY_FUNCTION_ENABLE_USB_CKO                (10) //  As Output
++#define  SECONDARY_FUNCTION_ENABLE_PCI_CCLKRUN_N          (12) //  Is Bidirectional
++#define  SECONDARY_FUNCTION_ENABLE_PCI_LOCK_N             (13) //  As Input
++#define  SECONDARY_FUNCTION_ENABLE_PCI_PERR_N             (14) //  Is Bidirectional
++#define  SECONDARY_FUNCTION_ENABLE_PCI_SERR_N             (15) //  As Output
++#define  SECONDARY_FUNCTION_ENABLE_MEM_DLLTGL             (16) //  As Output
++#define  SECONDARY_FUNCTION_ENABLE_SATA_OBS_RBC0          (17) //  As Output
++#define  SECONDARY_FUNCTION_ENABLE_PCI_CINT_N             (18) //  As Output
++#define  SECONDARY_FUNCTION_ENABLE_PCI_CSTSCHG_N          (19) //  As Output
++#define  SECONDARY_FUNCTION_ENABLE_PCI_CKO                (23) //  As Output
++#define  SECONDARY_FUNCTION_ENABLE_AUDIO_TXD0             (25) //  As Output
++#define  SECONDARY_FUNCTION_ENABLE_AUDIO_RXD0             (26) //  As Input
++#define  SECONDARY_FUNCTION_ENABLE_AUDIO_RXLRCK           (27) //  As Input
++#define  SECONDARY_FUNCTION_ENABLE_AUDIO_RX_BITCK         (28) //  As Input
++#define  SECONDARY_FUNCTION_ENABLE_AUDIO_TXD2             (29) //  As Output
++#define  SECONDARY_FUNCTION_ENABLE_AUDIO_RXD2             (30) //  As Input
++#define  SECONDARY_FUNCTION_ENABLE_AUDIO_TXD3             (31) //  As Output
++#define  SECONDARY_FUNCTION_ENABLE_AUDIO_RXD3             (32) //  As Input
++#define  SECONDARY_FUNCTION_ENABLE_AUDIO_RXD1             (33) //  As Input
++#define  SECONDARY_FUNCTION_ENABLE_AUDIO_TXD1             (34) //  As Output
++// GPIO Tertiary Function Enables
++#define  TERTIARY_FUNCTION_ENABLE_UART3_RI_N             (0) //  As Input
++#define  TERTIARY_FUNCTION_ENABLE_UART3_CD_N             (1) //  As Input
++#define  TERTIARY_FUNCTION_ENABLE_UART3_CTS_N            (2) //  As Input
++#define  TERTIARY_FUNCTION_ENABLE_UART3_DSR_N            (3) //  As Input
++#define  TERTIARY_FUNCTION_ENABLE_UART3_DTR_N            (4) //  As Output
++#define  TERTIARY_FUNCTION_ENABLE_UART3_RTS_N            (5) //  As Output
++#define  TERTIARY_FUNCTION_ENABLE_UART3_SIN              (6) //  As Input
++#define  TERTIARY_FUNCTION_ENABLE_UART3_SOUT             (7) //  As Output
++#define  TERTIARY_FUNCTION_ENABLE_UART2_DSR_N            (8) //  As Input
++#define  TERTIARY_FUNCTION_ENABLE_UART2_RTS_N            (9) //  As Output
++#define  TERTIARY_FUNCTION_ENABLE_UART2_SOUT             (20) //  As Output
++#define  TERTIARY_FUNCTION_ENABLE_UART2_SIN              (22) //  As Input
++#define  TERTIARY_FUNCTION_ENABLE_UART2_RI_N             (23) //  As Input
++#define  TERTIARY_FUNCTION_ENABLE_UART2_CD_N             (24) //  As Input
++#define  TERTIARY_FUNCTION_ENABLE_UART2_DTR_N            (25) //  As Output
++#define  TERTIARY_FUNCTION_ENABLE_UART2_CTS_N            (26) //  As Input
++#define  TERTIARY_FUNCTION_ENABLE_UART1_RTS_N            (27) //  As Output
++#define  TERTIARY_FUNCTION_ENABLE_UART1_CTS_N            (28) //  As Input
++#define  TERTIARY_FUNCTION_ENABLE_UART1_DSR_N            (29) //  As Input
++#define  TERTIARY_FUNCTION_ENABLE_UART1_CD_N             (30) //  As Input
++#define  TERTIARY_FUNCTION_ENABLE_UART1_SOUT             (31) //  As Output
++#define  TERTIARY_FUNCTION_ENABLE_UART1_SIN              (32) //  As Input
++#define  TERTIARY_FUNCTION_ENABLE_UART1_RI_N             (33) //  As Input
++#define  TERTIARY_FUNCTION_ENABLE_UART1_DTR_N            (34) //  As Output
+diff -Nurd linux-2.6.24.4/include/asm-arm/arch-hipox/hardware.h linux-2.6.24/include/asm-arm/arch-hipox/hardware.h
+--- linux-2.6.24.4/include/asm-arm/arch-hipox/hardware.h       1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/include/asm-arm/arch-hipox/hardware.h 2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,760 @@
 +/* linux/include/asm-arm/arch-hipox/hardware.h
 + *
@@ -50048,9 +45661,9 @@ diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/hardware.h linux-2.6.24-oxe81
 +#define PWM_CLOCK_REGISTER  (PWM_BASE+0X400)
 +
 +#endif // __ASM_ARCH_HARDWARE_H
-diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/i2s.h linux-2.6.24-oxe810/include/asm-arm/arch-hipox/i2s.h
---- linux-2.6.24/include/asm-arm/arch-hipox/i2s.h      1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/include/asm-arm/arch-hipox/i2s.h       2008-06-11 17:45:12.000000000 +0200
+diff -Nurd linux-2.6.24.4/include/asm-arm/arch-hipox/i2s.h linux-2.6.24/include/asm-arm/arch-hipox/i2s.h
+--- linux-2.6.24.4/include/asm-arm/arch-hipox/i2s.h    1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/include/asm-arm/arch-hipox/i2s.h      2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,1023 @@
 +/*
 + * linux/include/asm-arm/arch-hipox/i2s.h
@@ -51075,9 +46688,9 @@ diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/i2s.h linux-2.6.24-oxe810/inc
 +
 +#endif /* __ASM_ARM_ARCH_I2S_H */
 +
-diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/io.h linux-2.6.24-oxe810/include/asm-arm/arch-hipox/io.h
---- linux-2.6.24/include/asm-arm/arch-hipox/io.h       1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/include/asm-arm/arch-hipox/io.h        2008-06-11 17:45:12.000000000 +0200
+diff -Nurd linux-2.6.24.4/include/asm-arm/arch-hipox/io.h linux-2.6.24/include/asm-arm/arch-hipox/io.h
+--- linux-2.6.24.4/include/asm-arm/arch-hipox/io.h     1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/include/asm-arm/arch-hipox/io.h       2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,17 @@
 +/*
 + * linux/include/asm-arm/arch-hipox/io.h
@@ -51096,9 +46709,9 @@ diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/io.h linux-2.6.24-oxe810/incl
 +#define __mem_pci(a) (a)
 +
 +#endif //__ASM_ARM_ARCH_IO_H
-diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/irqs.h linux-2.6.24-oxe810/include/asm-arm/arch-hipox/irqs.h
---- linux-2.6.24/include/asm-arm/arch-hipox/irqs.h     1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/include/asm-arm/arch-hipox/irqs.h      2008-06-11 17:45:12.000000000 +0200
+diff -Nurd linux-2.6.24.4/include/asm-arm/arch-hipox/irqs.h linux-2.6.24/include/asm-arm/arch-hipox/irqs.h
+--- linux-2.6.24.4/include/asm-arm/arch-hipox/irqs.h   1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/include/asm-arm/arch-hipox/irqs.h     2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,42 @@
 +/* linux/include/asm-arm/arch-hipox/irqs.h
 + *
@@ -51142,9 +46755,49 @@ diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/irqs.h linux-2.6.24-oxe810/in
 +#define NR_IRQS 32
 +
 +#endif // __ASM_ARCH_IRQ_H
-diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/leon-power-button-prog.h linux-2.6.24-oxe810/include/asm-arm/arch-hipox/leon-power-button-prog.h
---- linux-2.6.24/include/asm-arm/arch-hipox/leon-power-button-prog.h   1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/include/asm-arm/arch-hipox/leon-power-button-prog.h    2008-07-01 09:46:51.000000000 +0200
+diff -Nurd linux-2.6.24.4/include/asm-arm/arch-hipox/leon.h linux-2.6.24/include/asm-arm/arch-hipox/leon.h
+--- linux-2.6.24.4/include/asm-arm/arch-hipox/leon.h   1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/include/asm-arm/arch-hipox/leon.h     2010-01-14 14:01:15.000000000 +0100
+@@ -0,0 +1,36 @@
++/*
++ * linux/arch/arm/mach-hipox/leon.h
++ *
++ * Copyright (C) 2005 Oxford Semiconductor Ltd
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++#ifdef CONFIG_SUPPORT_LEON
++
++#if !defined(__LEON_H__)
++#define __LEON_H__
++
++/**
++ * Load the LEON's program image into the memory as defined by the s-records
++ * holding the LEON program image, and begin execution at the start address
++ * defined by the s-records
++ */
++extern void init_copro(const s8 *srec, unsigned long arg);
++
++extern void shutdown_copro(void);
++
++#endif        //  #if !defined(__LEON_H__)
++#endif // CONFIG_SUPPORT_LEON
++
+diff -Nurd linux-2.6.24.4/include/asm-arm/arch-hipox/leon-power-button-prog.h linux-2.6.24/include/asm-arm/arch-hipox/leon-power-button-prog.h
+--- linux-2.6.24.4/include/asm-arm/arch-hipox/leon-power-button-prog.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/include/asm-arm/arch-hipox/leon-power-button-prog.h   2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,73 @@
 +static const s8 leon_srec[] =
 +"S01400006C656F6E2D706F7765722D627574746F6E1A\n"
@@ -51219,9 +46872,9 @@ diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/leon-power-button-prog.h linu
 +"S3159801E4F4C020C0008C01A001C200800080A06000E9\n"
 +"S3159801E50412BFFFFA8088601081C3E00801000000F9\n"
 +"S7059801E00081\n";
-diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/leon-program.h linux-2.6.24-oxe810/include/asm-arm/arch-hipox/leon-program.h
---- linux-2.6.24/include/asm-arm/arch-hipox/leon-program.h     1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/include/asm-arm/arch-hipox/leon-program.h      2008-07-01 09:46:44.000000000 +0200
+diff -Nurd linux-2.6.24.4/include/asm-arm/arch-hipox/leon-program.h linux-2.6.24/include/asm-arm/arch-hipox/leon-program.h
+--- linux-2.6.24.4/include/asm-arm/arch-hipox/leon-program.h   1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/include/asm-arm/arch-hipox/leon-program.h     2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,404 @@
 +static const s8 leon_srec[] =
 +"S00700006C656F6E4A\n"
@@ -51627,49 +47280,9 @@ diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/leon-program.h linux-2.6.24-o
 +"S3099801F9649C23BFF092\n"
 +"S30D9801F968FFC007FF0000FFFF35\n"
 +"S7059801E00081\n";
-diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/leon.h linux-2.6.24-oxe810/include/asm-arm/arch-hipox/leon.h
---- linux-2.6.24/include/asm-arm/arch-hipox/leon.h     1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/include/asm-arm/arch-hipox/leon.h      2008-06-11 17:45:12.000000000 +0200
-@@ -0,0 +1,36 @@
-+/*
-+ * linux/arch/arm/mach-hipox/leon.h
-+ *
-+ * Copyright (C) 2005 Oxford Semiconductor Ltd
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ */
-+#ifdef CONFIG_SUPPORT_LEON
-+
-+#if !defined(__LEON_H__)
-+#define __LEON_H__
-+
-+/**
-+ * Load the LEON's program image into the memory as defined by the s-records
-+ * holding the LEON program image, and begin execution at the start address
-+ * defined by the s-records
-+ */
-+extern void init_copro(const s8 *srec, unsigned long arg);
-+
-+extern void shutdown_copro(void);
-+
-+#endif        //  #if !defined(__LEON_H__)
-+#endif // CONFIG_SUPPORT_LEON
-+
-diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/memory.h linux-2.6.24-oxe810/include/asm-arm/arch-hipox/memory.h
---- linux-2.6.24/include/asm-arm/arch-hipox/memory.h   1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/include/asm-arm/arch-hipox/memory.h    2008-06-11 17:45:12.000000000 +0200
+diff -Nurd linux-2.6.24.4/include/asm-arm/arch-hipox/memory.h linux-2.6.24/include/asm-arm/arch-hipox/memory.h
+--- linux-2.6.24.4/include/asm-arm/arch-hipox/memory.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/include/asm-arm/arch-hipox/memory.h   2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,107 @@
 +/*
 + *  linux/include/asm-arm/arch-hipox/memory.h
@@ -51778,9 +47391,9 @@ diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/memory.h linux-2.6.24-oxe810/
 +#endif
 +
 +#endif // __ASM_ARCH_MEMORY_H
-diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/ox810sata.h linux-2.6.24-oxe810/include/asm-arm/arch-hipox/ox810sata.h
---- linux-2.6.24/include/asm-arm/arch-hipox/ox810sata.h        1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/include/asm-arm/arch-hipox/ox810sata.h 2008-06-11 17:45:12.000000000 +0200
+diff -Nurd linux-2.6.24.4/include/asm-arm/arch-hipox/ox810sata.h linux-2.6.24/include/asm-arm/arch-hipox/ox810sata.h
+--- linux-2.6.24.4/include/asm-arm/arch-hipox/ox810sata.h      1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/include/asm-arm/arch-hipox/ox810sata.h        2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,162 @@
 +/*
 + * linux/include/asm-arm/arch-hipox/sata.h
@@ -51944,9 +47557,9 @@ diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/ox810sata.h linux-2.6.24-oxe8
 +extern int hipoxsata_LBA_schemes_compatible( void );
 +
 +#endif  /*  #if !defined(__ASM_ARCH_SATA_H__) */
-diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/sata.h linux-2.6.24-oxe810/include/asm-arm/arch-hipox/sata.h
---- linux-2.6.24/include/asm-arm/arch-hipox/sata.h     1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/include/asm-arm/arch-hipox/sata.h      2008-06-11 17:45:12.000000000 +0200
+diff -Nurd linux-2.6.24.4/include/asm-arm/arch-hipox/sata.h linux-2.6.24/include/asm-arm/arch-hipox/sata.h
+--- linux-2.6.24.4/include/asm-arm/arch-hipox/sata.h   1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/include/asm-arm/arch-hipox/sata.h     2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,181 @@
 +/*
 + * linux/include/asm-arm/arch-hipox/sata.h
@@ -52129,9 +47742,9 @@ diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/sata.h linux-2.6.24-oxe810/in
 +extern int hipoxsata_LBA_schemes_compatible( void );
 +
 +#endif  /*  #if !defined(__ASM_ARCH_SATA_H__) */
-diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/system.h linux-2.6.24-oxe810/include/asm-arm/arch-hipox/system.h
---- linux-2.6.24/include/asm-arm/arch-hipox/system.h   1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/include/asm-arm/arch-hipox/system.h    2008-06-11 17:45:12.000000000 +0200
+diff -Nurd linux-2.6.24.4/include/asm-arm/arch-hipox/system.h linux-2.6.24/include/asm-arm/arch-hipox/system.h
+--- linux-2.6.24.4/include/asm-arm/arch-hipox/system.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/include/asm-arm/arch-hipox/system.h   2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,103 @@
 +/* linux/include/asm-arm/arch-hipox/system.h
 + *
@@ -52236,9 +47849,9 @@ diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/system.h linux-2.6.24-oxe810/
 +
 +#endif // __ASM_ARCH_SYSTEM_H
 +
-diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/taco.h linux-2.6.24-oxe810/include/asm-arm/arch-hipox/taco.h
---- linux-2.6.24/include/asm-arm/arch-hipox/taco.h     1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/include/asm-arm/arch-hipox/taco.h      2008-06-11 17:45:12.000000000 +0200
+diff -Nurd linux-2.6.24.4/include/asm-arm/arch-hipox/taco.h linux-2.6.24/include/asm-arm/arch-hipox/taco.h
+--- linux-2.6.24.4/include/asm-arm/arch-hipox/taco.h   1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/include/asm-arm/arch-hipox/taco.h     2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,227 @@
 +/*
 + * linux/include/asm-arm/arch-hipox/tacho.h
@@ -52467,9 +48080,9 @@ diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/taco.h linux-2.6.24-oxe810/in
 +
 +/* End oF File */
 +
-diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/timex.h linux-2.6.24-oxe810/include/asm-arm/arch-hipox/timex.h
---- linux-2.6.24/include/asm-arm/arch-hipox/timex.h    1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/include/asm-arm/arch-hipox/timex.h     2008-06-11 17:45:12.000000000 +0200
+diff -Nurd linux-2.6.24.4/include/asm-arm/arch-hipox/timex.h linux-2.6.24/include/asm-arm/arch-hipox/timex.h
+--- linux-2.6.24.4/include/asm-arm/arch-hipox/timex.h  1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/include/asm-arm/arch-hipox/timex.h    2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,23 @@
 +/* linux/include/asm-arm/arch-hipox/timex.h
 + *
@@ -52494,9 +48107,9 @@ diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/timex.h linux-2.6.24-oxe810/i
 +#define CLOCK_TICK_RATE (TIMER_1_PRESCALED_CLK)
 +
 +#endif // __ASM_ARCH_TIMEX_H
-diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/uncompress.h linux-2.6.24-oxe810/include/asm-arm/arch-hipox/uncompress.h
---- linux-2.6.24/include/asm-arm/arch-hipox/uncompress.h       1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/include/asm-arm/arch-hipox/uncompress.h        2008-06-11 17:45:12.000000000 +0200
+diff -Nurd linux-2.6.24.4/include/asm-arm/arch-hipox/uncompress.h linux-2.6.24/include/asm-arm/arch-hipox/uncompress.h
+--- linux-2.6.24.4/include/asm-arm/arch-hipox/uncompress.h     1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/include/asm-arm/arch-hipox/uncompress.h       2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,43 @@
 +/* linux/include/asm-arm/arch-hipox0/uncompress.h
 + *
@@ -52541,9 +48154,9 @@ diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/uncompress.h linux-2.6.24-oxe
 +#define arch_decomp_wdog()
 +
 +#endif // __ASM_ARCH_UNCOMPRESS_H
-diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/vmalloc.h linux-2.6.24-oxe810/include/asm-arm/arch-hipox/vmalloc.h
---- linux-2.6.24/include/asm-arm/arch-hipox/vmalloc.h  1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/include/asm-arm/arch-hipox/vmalloc.h   2008-06-11 17:45:12.000000000 +0200
+diff -Nurd linux-2.6.24.4/include/asm-arm/arch-hipox/vmalloc.h linux-2.6.24/include/asm-arm/arch-hipox/vmalloc.h
+--- linux-2.6.24.4/include/asm-arm/arch-hipox/vmalloc.h        1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/include/asm-arm/arch-hipox/vmalloc.h  2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,29 @@
 +/* linux/include/asm-arm/arch-hipox/vmalloc.h
 + *
@@ -52574,20 +48187,9 @@ diff -Nurd linux-2.6.24/include/asm-arm/arch-hipox/vmalloc.h linux-2.6.24-oxe810
 +#define VMALLOC_END            (0xE0000000)
 +
 +#endif // __ASM_ARCH_VMALLOC_H
-diff -Nurd linux-2.6.24/include/asm-arm/arch-pxa/pxa-regs.h linux-2.6.24-oxe810/include/asm-arm/arch-pxa/pxa-regs.h
---- linux-2.6.24/include/asm-arm/arch-pxa/pxa-regs.h   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/include/asm-arm/arch-pxa/pxa-regs.h    2008-06-11 17:45:03.000000000 +0200
-@@ -1669,6 +1669,7 @@
- #define SSCR1_RSRE            (1 << 20)       /* Receive Service Request Enable */
- #define SSCR1_TINTE           (1 << 19)       /* Receiver Time-out Interrupt enable */
- #define SSCR1_PINTE           (1 << 18)       /* Peripheral Trailing Byte Interupt Enable */
-+#define SSCR1_IFS             (1 << 16)       /* Invert Frame Signal */
- #define SSCR1_STRF            (1 << 15)       /* Select FIFO or EFWR */
- #define SSCR1_EFWR            (1 << 14)       /* Enable FIFO Write/Read */
-diff -Nurd linux-2.6.24/include/asm-arm/assembler.h linux-2.6.24-oxe810/include/asm-arm/assembler.h
---- linux-2.6.24/include/asm-arm/assembler.h   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/include/asm-arm/assembler.h    2008-06-11 17:45:14.000000000 +0200
+diff -Nurd linux-2.6.24.4/include/asm-arm/assembler.h linux-2.6.24/include/asm-arm/assembler.h
+--- linux-2.6.24.4/include/asm-arm/assembler.h 2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/include/asm-arm/assembler.h   2010-01-14 14:01:15.000000000 +0100
 @@ -48,8 +48,10 @@
  
  /*
@@ -52600,9 +48202,9 @@ diff -Nurd linux-2.6.24/include/asm-arm/assembler.h linux-2.6.24-oxe810/include/
  #define PLD(code...)  code
  #else
  #define PLD(code...)
-diff -Nurd linux-2.6.24/include/asm-arm/io.h linux-2.6.24-oxe810/include/asm-arm/io.h
---- linux-2.6.24/include/asm-arm/io.h  2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/include/asm-arm/io.h   2008-06-11 17:45:14.000000000 +0200
+diff -Nurd linux-2.6.24.4/include/asm-arm/io.h linux-2.6.24/include/asm-arm/io.h
+--- linux-2.6.24.4/include/asm-arm/io.h        2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/include/asm-arm/io.h  2010-01-14 14:01:15.000000000 +0100
 @@ -108,27 +108,24 @@
   *
   * The {in,out}[bwl] macros are for emulating x86-style PCI/ISA IO space.
@@ -52646,9 +48248,9 @@ diff -Nurd linux-2.6.24/include/asm-arm/io.h linux-2.6.24-oxe810/include/asm-arm
  
  #define outb_p(val,port)      outb((val),(port))
  #define outw_p(val,port)      outw((val),(port))
-diff -Nurd linux-2.6.24/include/asm-arm/uaccess.h linux-2.6.24-oxe810/include/asm-arm/uaccess.h
---- linux-2.6.24/include/asm-arm/uaccess.h     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/include/asm-arm/uaccess.h      2008-06-11 17:45:14.000000000 +0200
+diff -Nurd linux-2.6.24.4/include/asm-arm/uaccess.h linux-2.6.24/include/asm-arm/uaccess.h
+--- linux-2.6.24.4/include/asm-arm/uaccess.h   2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/include/asm-arm/uaccess.h     2010-01-14 14:01:15.000000000 +0100
 @@ -383,9 +383,30 @@
  
  
@@ -52728,9 +48330,9 @@ diff -Nurd linux-2.6.24/include/asm-arm/uaccess.h linux-2.6.24-oxe810/include/as
        return n;
  }
  
-diff -Nurd linux-2.6.24/include/asm-arm/unaligned.h linux-2.6.24-oxe810/include/asm-arm/unaligned.h
---- linux-2.6.24/include/asm-arm/unaligned.h   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/include/asm-arm/unaligned.h    2008-06-11 17:45:14.000000000 +0200
+diff -Nurd linux-2.6.24.4/include/asm-arm/unaligned.h linux-2.6.24/include/asm-arm/unaligned.h
+--- linux-2.6.24.4/include/asm-arm/unaligned.h 2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/include/asm-arm/unaligned.h   2010-01-14 14:01:15.000000000 +0100
 @@ -40,16 +40,16 @@
   */
  
@@ -52752,9 +48354,9 @@ diff -Nurd linux-2.6.24/include/asm-arm/unaligned.h linux-2.6.24-oxe810/include/
  
  #define __get_unaligned_8_le(__p)                                     \
        ((unsigned long long)__get_unaligned_4_le((__p+4)) << 32 |      \
-diff -Nurd linux-2.6.24/include/asm-arm/unistd.h linux-2.6.24-oxe810/include/asm-arm/unistd.h
---- linux-2.6.24/include/asm-arm/unistd.h      2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/include/asm-arm/unistd.h       2008-06-11 17:45:14.000000000 +0200
+diff -Nurd linux-2.6.24.4/include/asm-arm/unistd.h linux-2.6.24/include/asm-arm/unistd.h
+--- linux-2.6.24.4/include/asm-arm/unistd.h    2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/include/asm-arm/unistd.h      2010-01-14 14:01:15.000000000 +0100
 @@ -379,6 +379,7 @@
  #define __NR_timerfd                  (__NR_SYSCALL_BASE+350)
  #define __NR_eventfd                  (__NR_SYSCALL_BASE+351)
@@ -52763,127 +48365,9 @@ diff -Nurd linux-2.6.24/include/asm-arm/unistd.h linux-2.6.24-oxe810/include/asm
  
  /*
   * The following SWIs are ARM private.
-diff -Nurd linux-2.6.24/include/asm-powerpc/pmac_feature.h linux-2.6.24-oxe810/include/asm-powerpc/pmac_feature.h
---- linux-2.6.24/include/asm-powerpc/pmac_feature.h    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/include/asm-powerpc/pmac_feature.h     2008-06-11 17:44:57.000000000 +0200
-@@ -392,6 +392,14 @@
- #define UN_BIS(r,v)   (UN_OUT((r), UN_IN(r) | (v)))
- #define UN_BIC(r,v)   (UN_OUT((r), UN_IN(r) & ~(v)))
-+/* Uninorth variant:
-+ *
-+ * 0 = not uninorth
-+ * 1 = U1.x or U2.x
-+ * 3 = U3
-+ * 4 = U4
-+ */
-+extern int pmac_get_uninorth_variant(void);
- #endif /* __ASM_POWERPC_PMAC_FEATURE_H */
- #endif /* __KERNEL__ */
-diff -Nurd linux-2.6.24/include/asm-x86/apic_32.h linux-2.6.24-oxe810/include/asm-x86/apic_32.h
---- linux-2.6.24/include/asm-x86/apic_32.h     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/include/asm-x86/apic_32.h      2008-06-11 17:44:30.000000000 +0200
-@@ -109,7 +109,7 @@
- extern void setup_secondary_APIC_clock (void);
- extern int APIC_init_uniprocessor (void);
--extern void enable_NMI_through_LVT0 (void * dummy);
-+extern void enable_NMI_through_LVT0(void);
- #define ARCH_APICTIMER_STOPS_ON_C3    1
-diff -Nurd linux-2.6.24/include/asm-x86/futex_32.h linux-2.6.24-oxe810/include/asm-x86/futex_32.h
---- linux-2.6.24/include/asm-x86/futex_32.h    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/include/asm-x86/futex_32.h     2008-06-11 17:44:30.000000000 +0200
-@@ -28,7 +28,7 @@
- "1:   movl    %2, %0\n\
-       movl    %0, %3\n"                                       \
-       insn "\n"                                               \
--"2:   " LOCK_PREFIX "cmpxchgl %3, %2\n\
-+"2:   lock ; cmpxchgl %3, %2\n\
-       jnz     1b\n\
- 3:    .section .fixup,\"ax\"\n\
- 4:    mov     %5, %1\n\
-@@ -68,7 +68,7 @@
- #endif
-               switch (op) {
-               case FUTEX_OP_ADD:
--                      __futex_atomic_op1(LOCK_PREFIX "xaddl %0, %2", ret,
-+                      __futex_atomic_op1("lock ; xaddl %0, %2", ret,
-                                          oldval, uaddr, oparg);
-                       break;
-               case FUTEX_OP_OR:
-@@ -111,7 +111,7 @@
-               return -EFAULT;
-       __asm__ __volatile__(
--              "1:     " LOCK_PREFIX "cmpxchgl %3, %1          \n"
-+              "1:     lock ; cmpxchgl %3, %1                  \n"
-               "2:     .section .fixup, \"ax\"                 \n"
-               "3:     mov     %2, %0                          \n"
-diff -Nurd linux-2.6.24/include/asm-x86/futex_64.h linux-2.6.24-oxe810/include/asm-x86/futex_64.h
---- linux-2.6.24/include/asm-x86/futex_64.h    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/include/asm-x86/futex_64.h     2008-06-11 17:44:30.000000000 +0200
-@@ -27,7 +27,7 @@
- "1:   movl    %2, %0\n\
-       movl    %0, %3\n"                                       \
-       insn "\n"                                               \
--"2:   " LOCK_PREFIX "cmpxchgl %3, %2\n\
-+"2:   lock ; cmpxchgl %3, %2\n\
-       jnz     1b\n\
- 3:    .section .fixup,\"ax\"\n\
- 4:    mov     %5, %1\n\
-@@ -62,7 +62,7 @@
-               __futex_atomic_op1("xchgl %0, %2", ret, oldval, uaddr, oparg);
-               break;
-       case FUTEX_OP_ADD:
--              __futex_atomic_op1(LOCK_PREFIX "xaddl %0, %2", ret, oldval,
-+              __futex_atomic_op1("lock ; xaddl %0, %2", ret, oldval,
-                                  uaddr, oparg);
-               break;
-       case FUTEX_OP_OR:
-@@ -101,7 +101,7 @@
-               return -EFAULT;
-       __asm__ __volatile__(
--              "1:     " LOCK_PREFIX "cmpxchgl %3, %1          \n"
-+              "1:     lock ; cmpxchgl %3, %1                  \n"
-               "2:     .section .fixup, \"ax\"                 \n"
-               "3:     mov     %2, %0                          \n"
-diff -Nurd linux-2.6.24/include/asm-x86/io_apic_64.h linux-2.6.24-oxe810/include/asm-x86/io_apic_64.h
---- linux-2.6.24/include/asm-x86/io_apic_64.h  2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/include/asm-x86/io_apic_64.h   2008-06-11 17:44:30.000000000 +0200
-@@ -129,7 +129,7 @@
- extern int sis_apic_bug; /* dummy */ 
--void enable_NMI_through_LVT0 (void * dummy);
-+void enable_NMI_through_LVT0(void);
- extern spinlock_t i8259A_lock;
-diff -Nurd linux-2.6.24/include/asm-x86/processor_32.h linux-2.6.24-oxe810/include/asm-x86/processor_32.h
---- linux-2.6.24/include/asm-x86/processor_32.h        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/include/asm-x86/processor_32.h 2008-06-11 17:44:30.000000000 +0200
-@@ -712,9 +712,10 @@
- #define ASM_NOP6 K7_NOP6
- #define ASM_NOP7 K7_NOP7
- #define ASM_NOP8 K7_NOP8
--#elif defined(CONFIG_M686) || defined(CONFIG_MPENTIUMII) || \
-+#elif (defined(CONFIG_M686) || defined(CONFIG_MPENTIUMII) || \
-       defined(CONFIG_MPENTIUMIII) || defined(CONFIG_MPENTIUMM) || \
--      defined(CONFIG_MCORE2) || defined(CONFIG_PENTIUM4)
-+      defined(CONFIG_MCORE2) || defined(CONFIG_PENTIUM4)) && \
-+      !defined(CONFIG_X86_GENERIC)
- #define ASM_NOP1 P6_NOP1
- #define ASM_NOP2 P6_NOP2
- #define ASM_NOP3 P6_NOP3
-diff -Nurd linux-2.6.24/include/linux/bio.h linux-2.6.24-oxe810/include/linux/bio.h
---- linux-2.6.24/include/linux/bio.h   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/include/linux/bio.h    2008-06-11 17:45:39.000000000 +0200
+diff -Nurd linux-2.6.24.4/include/linux/bio.h linux-2.6.24/include/linux/bio.h
+--- linux-2.6.24.4/include/linux/bio.h 2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/include/linux/bio.h   2010-01-14 14:01:15.000000000 +0100
 @@ -114,6 +114,15 @@
        void                    *bi_private;
  
@@ -52900,9 +48384,9 @@ diff -Nurd linux-2.6.24/include/linux/bio.h linux-2.6.24-oxe810/include/linux/bi
  };
  
  /*
-diff -Nurd linux-2.6.24/include/linux/byteorder/generic.h linux-2.6.24-oxe810/include/linux/byteorder/generic.h
---- linux-2.6.24/include/linux/byteorder/generic.h     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/include/linux/byteorder/generic.h      2008-06-11 17:45:26.000000000 +0200
+diff -Nurd linux-2.6.24.4/include/linux/byteorder/generic.h linux-2.6.24/include/linux/byteorder/generic.h
+--- linux-2.6.24.4/include/linux/byteorder/generic.h   2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/include/linux/byteorder/generic.h     2010-01-14 14:01:15.000000000 +0100
 @@ -146,6 +146,36 @@
  #define htons(x) ___htons(x)
  #define ntohs(x) ___ntohs(x)
@@ -52940,9 +48424,9 @@ diff -Nurd linux-2.6.24/include/linux/byteorder/generic.h linux-2.6.24-oxe810/in
  #endif /* KERNEL */
  
  #endif /* _LINUX_BYTEORDER_GENERIC_H */
-diff -Nurd linux-2.6.24/include/linux/byteorder/swab.h linux-2.6.24-oxe810/include/linux/byteorder/swab.h
---- linux-2.6.24/include/linux/byteorder/swab.h        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/include/linux/byteorder/swab.h 2008-06-11 17:45:26.000000000 +0200
+diff -Nurd linux-2.6.24.4/include/linux/byteorder/swab.h linux-2.6.24/include/linux/byteorder/swab.h
+--- linux-2.6.24.4/include/linux/byteorder/swab.h      2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/include/linux/byteorder/swab.h        2010-01-14 14:01:15.000000000 +0100
 @@ -61,26 +61,37 @@
   * how U/UL/ULL map to __u16, __u32, __u64. At least not in a portable way.
   */
@@ -53009,28 +48493,9 @@ diff -Nurd linux-2.6.24/include/linux/byteorder/swab.h linux-2.6.24-oxe810/inclu
  /*
   * provide defaults when no architecture-specific optimization is detected
   */
-diff -Nurd linux-2.6.24/include/linux/dmi.h linux-2.6.24-oxe810/include/linux/dmi.h
---- linux-2.6.24/include/linux/dmi.h   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/include/linux/dmi.h    2008-06-11 17:45:39.000000000 +0200
-@@ -79,7 +79,6 @@
- extern int dmi_get_year(int field);
- extern int dmi_name_in_vendors(const char *str);
- extern int dmi_available;
--extern char *dmi_get_slot(int slot);
- #else
-@@ -90,7 +89,6 @@
- static inline int dmi_get_year(int year) { return 0; }
- static inline int dmi_name_in_vendors(const char *s) { return 0; }
- #define dmi_available 0
--static inline char *dmi_get_slot(int slot) { return NULL; }
- #endif
-diff -Nurd linux-2.6.24/include/linux/fs.h linux-2.6.24-oxe810/include/linux/fs.h
---- linux-2.6.24/include/linux/fs.h    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/include/linux/fs.h     2008-06-11 17:45:39.000000000 +0200
+diff -Nurd linux-2.6.24.4/include/linux/fs.h linux-2.6.24/include/linux/fs.h
+--- linux-2.6.24.4/include/linux/fs.h  2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/include/linux/fs.h    2010-01-14 14:01:15.000000000 +0100
 @@ -1147,7 +1147,7 @@
        int error;
  } read_descriptor_t;
@@ -53075,43 +48540,9 @@ diff -Nurd linux-2.6.24/include/linux/fs.h linux-2.6.24-oxe810/include/linux/fs.
  /* fs/splice.c */
  extern ssize_t generic_file_splice_read(struct file *, loff_t *,
                struct pipe_inode_info *, size_t, unsigned int);
-diff -Nurd linux-2.6.24/include/linux/futex.h linux-2.6.24-oxe810/include/linux/futex.h
---- linux-2.6.24/include/linux/futex.h 2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/include/linux/futex.h  2008-06-11 17:45:38.000000000 +0200
-@@ -153,6 +153,7 @@
- #ifdef CONFIG_FUTEX
- extern void exit_robust_list(struct task_struct *curr);
- extern void exit_pi_state_list(struct task_struct *curr);
-+extern int futex_cmpxchg_enabled;
- #else
- static inline void exit_robust_list(struct task_struct *curr)
- {
-diff -Nurd linux-2.6.24/include/linux/hrtimer.h linux-2.6.24-oxe810/include/linux/hrtimer.h
---- linux-2.6.24/include/linux/hrtimer.h       2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/include/linux/hrtimer.h        2008-06-11 17:45:39.000000000 +0200
-@@ -300,7 +300,7 @@
- /* Precise sleep: */
- extern long hrtimer_nanosleep(struct timespec *rqtp,
--                            struct timespec *rmtp,
-+                            struct timespec __user *rmtp,
-                             const enum hrtimer_mode mode,
-                             const clockid_t clockid);
- extern long hrtimer_nanosleep_restart(struct restart_block *restart_block);
-diff -Nurd linux-2.6.24/include/linux/hugetlb.h linux-2.6.24-oxe810/include/linux/hugetlb.h
---- linux-2.6.24/include/linux/hugetlb.h       2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/include/linux/hugetlb.h        2008-06-11 17:45:39.000000000 +0200
-@@ -17,6 +17,7 @@
- }
- int hugetlb_sysctl_handler(struct ctl_table *, int, struct file *, void __user *, size_t *, loff_t *);
-+int hugetlb_overcommit_handler(struct ctl_table *, int, struct file *, void __user *, size_t *, loff_t *);
- int hugetlb_treat_movable_handler(struct ctl_table *, int, struct file *, void __user *, size_t *, loff_t *);
- int copy_hugetlb_page_range(struct mm_struct *, struct mm_struct *, struct vm_area_struct *);
- int follow_hugetlb_page(struct mm_struct *, struct vm_area_struct *, struct page **, struct vm_area_struct **, unsigned long *, int *, int, int);
-diff -Nurd linux-2.6.24/include/linux/i2c-id.h linux-2.6.24-oxe810/include/linux/i2c-id.h
---- linux-2.6.24/include/linux/i2c-id.h        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/include/linux/i2c-id.h 2008-06-11 17:45:39.000000000 +0200
+diff -Nurd linux-2.6.24.4/include/linux/i2c-id.h linux-2.6.24/include/linux/i2c-id.h
+--- linux-2.6.24.4/include/linux/i2c-id.h      2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/include/linux/i2c-id.h        2010-01-14 14:01:15.000000000 +0100
 @@ -203,6 +203,7 @@
  #define I2C_HW_B_CX2341X      0x010020 /* Conexant CX2341X MPEG encoder cards */
  #define I2C_HW_B_INTELFB      0x010021 /* intel framebuffer driver */
@@ -53120,34 +48551,9 @@ diff -Nurd linux-2.6.24/include/linux/i2c-id.h linux-2.6.24-oxe810/include/linux
  
  /* --- PCF 8584 based algorithms                                      */
  #define I2C_HW_P_LP           0x020000 /* Parallel port interface */
-diff -Nurd linux-2.6.24/include/linux/irq.h linux-2.6.24-oxe810/include/linux/irq.h
---- linux-2.6.24/include/linux/irq.h   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/include/linux/irq.h    2008-06-11 17:45:39.000000000 +0200
-@@ -367,6 +367,9 @@
-       __set_irq_handler(irq, handle, 1, NULL);
- }
-+extern void set_irq_noprobe(unsigned int irq);
-+extern void set_irq_probe(unsigned int irq);
-+
- /* Handle dynamic irq creation and destruction */
- extern int create_irq(void);
- extern void destroy_irq(unsigned int irq);
-diff -Nurd linux-2.6.24/include/linux/ktime.h linux-2.6.24-oxe810/include/linux/ktime.h
---- linux-2.6.24/include/linux/ktime.h 2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/include/linux/ktime.h  2008-06-11 17:45:39.000000000 +0200
-@@ -310,6 +310,8 @@
-       return ktime_sub_ns(kt, usec * 1000);
- }
-+extern ktime_t ktime_add_safe(const ktime_t lhs, const ktime_t rhs);
-+
- /*
-  * The resolution of the clocks. The resolution value is returned in
-  * the clock_getres() system call to give application programmers an
-diff -Nurd linux-2.6.24/include/linux/leds.h linux-2.6.24-oxe810/include/linux/leds.h
---- linux-2.6.24/include/linux/leds.h  2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/include/linux/leds.h   2008-06-11 17:45:38.000000000 +0200
+diff -Nurd linux-2.6.24.4/include/linux/leds.h linux-2.6.24/include/linux/leds.h
+--- linux-2.6.24.4/include/linux/leds.h        2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/include/linux/leds.h  2010-01-14 14:01:15.000000000 +0100
 @@ -123,5 +123,11 @@
        struct gpio_led *leds;
  };
@@ -53160,9 +48566,9 @@ diff -Nurd linux-2.6.24/include/linux/leds.h linux-2.6.24-oxe810/include/linux/l
 +#endif
  
  #endif                /* __LINUX_LEDS_H_INCLUDED */
-diff -Nurd linux-2.6.24/include/linux/libata.h linux-2.6.24-oxe810/include/linux/libata.h
---- linux-2.6.24/include/linux/libata.h        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/include/linux/libata.h 2008-06-11 17:45:39.000000000 +0200
+diff -Nurd linux-2.6.24.4/include/linux/libata.h linux-2.6.24/include/linux/libata.h
+--- linux-2.6.24.4/include/linux/libata.h      2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/include/linux/libata.h        2010-01-14 14:01:15.000000000 +0100
 @@ -238,7 +238,7 @@
        /* various lengths of time */
        ATA_TMOUT_BOOT          = 30 * HZ,      /* heuristic */
@@ -53206,9 +48612,9 @@ diff -Nurd linux-2.6.24/include/linux/libata.h linux-2.6.24-oxe810/include/linux
  };
  
  struct ata_port_info {
-diff -Nurd linux-2.6.24/include/linux/mii.h linux-2.6.24-oxe810/include/linux/mii.h
---- linux-2.6.24/include/linux/mii.h   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/include/linux/mii.h    2008-06-11 17:45:39.000000000 +0200
+diff -Nurd linux-2.6.24.4/include/linux/mii.h linux-2.6.24/include/linux/mii.h
+--- linux-2.6.24.4/include/linux/mii.h 2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/include/linux/mii.h   2010-01-14 14:01:15.000000000 +0100
 @@ -21,18 +21,18 @@
  #define MII_EXPANSION       0x06        /* Expansion register          */
  #define MII_CTRL1000        0x09        /* 1000BASE-T control          */
@@ -53308,38 +48714,9 @@ diff -Nurd linux-2.6.24/include/linux/mii.h linux-2.6.24-oxe810/include/linux/mi
  /**
   * mii_duplex
   * @duplex_lock: Non-zero if duplex is locked at full
-diff -Nurd linux-2.6.24/include/linux/moduleparam.h linux-2.6.24-oxe810/include/linux/moduleparam.h
---- linux-2.6.24/include/linux/moduleparam.h   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/include/linux/moduleparam.h    2008-06-11 17:45:39.000000000 +0200
-@@ -62,6 +62,16 @@
-       void *elem;
- };
-+/* On alpha, ia64 and ppc64 relocations to global data cannot go into
-+   read-only sections (which is part of respective UNIX ABI on these
-+   platforms). So 'const' makes no sense and even causes compile failures
-+   with some compilers. */
-+#if defined(CONFIG_ALPHA) || defined(CONFIG_IA64) || defined(CONFIG_PPC64)
-+#define __moduleparam_const
-+#else
-+#define __moduleparam_const const
-+#endif
-+
- /* This is the fundamental function for registering boot/module
-    parameters.  perm sets the visibility in sysfs: 000 means it's
-    not there, read bits mean it's readable, write bits mean it's
-@@ -71,7 +81,7 @@
-       static int __param_perm_check_##name __attribute__((unused)) =  \
-       BUILD_BUG_ON_ZERO((perm) < 0 || (perm) > 0777 || ((perm) & 2)); \
-       static const char __param_str_##name[] = prefix #name;          \
--      static struct kernel_param const __param_##name                 \
-+      static struct kernel_param __moduleparam_const __param_##name   \
-       __attribute_used__                                              \
-     __attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \
-       = { __param_str_##name, perm, set, get, { arg } }
-diff -Nurd linux-2.6.24/include/linux/net.h linux-2.6.24-oxe810/include/linux/net.h
---- linux-2.6.24/include/linux/net.h   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/include/linux/net.h    2008-06-11 17:45:39.000000000 +0200
+diff -Nurd linux-2.6.24.4/include/linux/net.h linux-2.6.24/include/linux/net.h
+--- linux-2.6.24.4/include/linux/net.h 2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/include/linux/net.h   2010-01-14 14:01:15.000000000 +0100
 @@ -172,6 +172,8 @@
                                      struct vm_area_struct * vma);
        ssize_t         (*sendpage)  (struct socket *sock, struct page *page,
@@ -53349,9 +48726,9 @@ diff -Nurd linux-2.6.24/include/linux/net.h linux-2.6.24-oxe810/include/linux/ne
  };
  
  struct net_proto_family {
-diff -Nurd linux-2.6.24/include/linux/raid/raid1.h linux-2.6.24-oxe810/include/linux/raid/raid1.h
---- linux-2.6.24/include/linux/raid/raid1.h    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/include/linux/raid/raid1.h     2008-06-11 17:45:26.000000000 +0200
+diff -Nurd linux-2.6.24.4/include/linux/raid/raid1.h linux-2.6.24/include/linux/raid/raid1.h
+--- linux-2.6.24.4/include/linux/raid/raid1.h  2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/include/linux/raid/raid1.h    2010-01-14 14:01:15.000000000 +0100
 @@ -61,6 +61,10 @@
  
        mempool_t *r1bio_pool;
@@ -53363,9 +48740,9 @@ diff -Nurd linux-2.6.24/include/linux/raid/raid1.h linux-2.6.24-oxe810/include/l
  };
  
  typedef struct r1_private_data_s conf_t;
-diff -Nurd linux-2.6.24/include/linux/serial_reg.h linux-2.6.24-oxe810/include/linux/serial_reg.h
---- linux-2.6.24/include/linux/serial_reg.h    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/include/linux/serial_reg.h     2008-06-11 17:45:39.000000000 +0200
+diff -Nurd linux-2.6.24.4/include/linux/serial_reg.h linux-2.6.24/include/linux/serial_reg.h
+--- linux-2.6.24.4/include/linux/serial_reg.h  2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/include/linux/serial_reg.h    2010-01-14 14:01:15.000000000 +0100
 @@ -133,6 +133,15 @@
  
  #define UART_SCR      7       /* I/O: Scratch Register */
@@ -53382,9 +48759,9 @@ diff -Nurd linux-2.6.24/include/linux/serial_reg.h linux-2.6.24-oxe810/include/l
  /*
   * DLAB=1
   */
-diff -Nurd linux-2.6.24/include/linux/syscalls.h linux-2.6.24-oxe810/include/linux/syscalls.h
---- linux-2.6.24/include/linux/syscalls.h      2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/include/linux/syscalls.h       2008-06-11 17:45:39.000000000 +0200
+diff -Nurd linux-2.6.24.4/include/linux/syscalls.h linux-2.6.24/include/linux/syscalls.h
+--- linux-2.6.24.4/include/linux/syscalls.h    2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/include/linux/syscalls.h      2010-01-14 14:01:15.000000000 +0100
 @@ -611,6 +611,7 @@
                            const struct itimerspec __user *utmr);
  asmlinkage long sys_eventfd(unsigned int count);
@@ -53393,9 +48770,9 @@ diff -Nurd linux-2.6.24/include/linux/syscalls.h linux-2.6.24-oxe810/include/lin
  
  int kernel_execve(const char *filename, char *const argv[], char *const envp[]);
  
-diff -Nurd linux-2.6.24/include/linux/trustees.h linux-2.6.24-oxe810/include/linux/trustees.h
---- linux-2.6.24/include/linux/trustees.h      1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/include/linux/trustees.h       2008-06-11 17:45:39.000000000 +0200
+diff -Nurd linux-2.6.24.4/include/linux/trustees.h linux-2.6.24/include/linux/trustees.h
+--- linux-2.6.24.4/include/linux/trustees.h    1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/include/linux/trustees.h      2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,108 @@
 +/*
 + * Trustees ACL Project
@@ -53505,48 +48882,9 @@ diff -Nurd linux-2.6.24/include/linux/trustees.h linux-2.6.24-oxe810/include/lin
 +#define TRUSTEE_COMMAND_MAKE_IC 5
 +
 +#endif /* _LINUX_TRUSTEE_STRUCT_H */
-diff -Nurd linux-2.6.24/include/linux/wait.h linux-2.6.24-oxe810/include/linux/wait.h
---- linux-2.6.24/include/linux/wait.h  2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/include/linux/wait.h   2008-06-11 17:45:39.000000000 +0200
-@@ -161,6 +161,22 @@
- #define       wake_up_locked(x)               __wake_up_locked((x), TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE)
- #define wake_up_interruptible_sync(x)   __wake_up_sync((x),TASK_INTERRUPTIBLE, 1)
-+#ifdef CONFIG_DEBUG_LOCK_ALLOC
-+/*
-+ * macro to avoid include hell
-+ */
-+#define wake_up_nested(x, s)                                          \
-+do {                                                                  \
-+      unsigned long flags;                                            \
-+                                                                      \
-+      spin_lock_irqsave_nested(&(x)->lock, flags, (s));               \
-+      wake_up_locked(x);                                              \
-+      spin_unlock_irqrestore(&(x)->lock, flags);                      \
-+} while (0)
-+#else
-+#define wake_up_nested(x, s)          wake_up(x)
-+#endif
-+
- #define __wait_event(wq, condition)                                   \
- do {                                                                  \
-       DEFINE_WAIT(__wait);                                            \
-diff -Nurd linux-2.6.24/include/net/inet_sock.h linux-2.6.24-oxe810/include/net/inet_sock.h
---- linux-2.6.24/include/net/inet_sock.h       2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/include/net/inet_sock.h        2008-06-11 17:44:45.000000000 +0200
-@@ -175,7 +175,8 @@
- static inline unsigned int inet_ehashfn(const __be32 laddr, const __u16 lport,
-                                       const __be32 faddr, const __be16 fport)
- {
--      return jhash_2words((__force __u32) laddr ^ (__force __u32) faddr,
-+      return jhash_3words((__force __u32) laddr,
-+                          (__force __u32) faddr,
-                           ((__u32) lport) << 16 | (__force __u32)fport,
-                           inet_ehash_secret);
- }
-diff -Nurd linux-2.6.24/include/net/sock.h linux-2.6.24-oxe810/include/net/sock.h
---- linux-2.6.24/include/net/sock.h    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/include/net/sock.h     2008-06-11 17:44:45.000000000 +0200
+diff -Nurd linux-2.6.24.4/include/net/sock.h linux-2.6.24/include/net/sock.h
+--- linux-2.6.24.4/include/net/sock.h  2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/include/net/sock.h    2010-01-14 14:01:15.000000000 +0100
 @@ -549,6 +549,8 @@
                                        int *addr_len);
        int                     (*sendpage)(struct sock *sk, struct page *page,
@@ -53556,9 +48894,9 @@ diff -Nurd linux-2.6.24/include/net/sock.h linux-2.6.24-oxe810/include/net/sock.
        int                     (*bind)(struct sock *sk, 
                                        struct sockaddr *uaddr, int addr_len);
  
-diff -Nurd linux-2.6.24/include/net/tcp.h linux-2.6.24-oxe810/include/net/tcp.h
---- linux-2.6.24/include/net/tcp.h     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/include/net/tcp.h      2008-06-11 17:44:45.000000000 +0200
+diff -Nurd linux-2.6.24.4/include/net/tcp.h linux-2.6.24/include/net/tcp.h
+--- linux-2.6.24.4/include/net/tcp.h   2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/include/net/tcp.h     2010-01-14 14:01:15.000000000 +0100
 @@ -285,6 +285,7 @@
  extern int                    tcp_sendmsg(struct kiocb *iocb, struct socket *sock,
                                            struct msghdr *msg, size_t size);
@@ -53567,587 +48905,9 @@ diff -Nurd linux-2.6.24/include/net/tcp.h linux-2.6.24-oxe810/include/net/tcp.h
  
  extern int                    tcp_ioctl(struct sock *sk, 
                                          int cmd, 
-diff -Nurd linux-2.6.24/kernel/audit.c linux-2.6.24-oxe810/kernel/audit.c
---- linux-2.6.24/kernel/audit.c        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/kernel/audit.c 2008-06-11 17:43:47.000000000 +0200
-@@ -1200,13 +1200,17 @@
- static inline int audit_expand(struct audit_buffer *ab, int extra)
- {
-       struct sk_buff *skb = ab->skb;
--      int ret = pskb_expand_head(skb, skb_headroom(skb), extra,
--                                 ab->gfp_mask);
-+      int oldtail = skb_tailroom(skb);
-+      int ret = pskb_expand_head(skb, 0, extra, ab->gfp_mask);
-+      int newtail = skb_tailroom(skb);
-+
-       if (ret < 0) {
-               audit_log_lost("out of memory in audit_expand");
-               return 0;
-       }
--      return skb_tailroom(skb);
-+
-+      skb->truesize += newtail - oldtail;
-+      return newtail;
- }
- /*
-diff -Nurd linux-2.6.24/kernel/compat.c linux-2.6.24-oxe810/kernel/compat.c
---- linux-2.6.24/kernel/compat.c       2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/kernel/compat.c        2008-06-11 17:43:47.000000000 +0200
-@@ -40,10 +40,36 @@
-                       __put_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0;
- }
-+static long compat_nanosleep_restart(struct restart_block *restart)
-+{
-+      struct compat_timespec __user *rmtp;
-+      struct timespec rmt;
-+      mm_segment_t oldfs;
-+      long ret;
-+
-+      rmtp = (struct compat_timespec __user *)(restart->arg1);
-+      restart->arg1 = (unsigned long)&rmt;
-+      oldfs = get_fs();
-+      set_fs(KERNEL_DS);
-+      ret = hrtimer_nanosleep_restart(restart);
-+      set_fs(oldfs);
-+
-+      if (ret) {
-+              restart->fn = compat_nanosleep_restart;
-+              restart->arg1 = (unsigned long)rmtp;
-+
-+              if (rmtp && put_compat_timespec(&rmt, rmtp))
-+                      return -EFAULT;
-+      }
-+
-+      return ret;
-+}
-+
- asmlinkage long compat_sys_nanosleep(struct compat_timespec __user *rqtp,
-                                    struct compat_timespec __user *rmtp)
- {
-       struct timespec tu, rmt;
-+      mm_segment_t oldfs;
-       long ret;
-       if (get_compat_timespec(&tu, rqtp))
-@@ -52,11 +78,21 @@
-       if (!timespec_valid(&tu))
-               return -EINVAL;
--      ret = hrtimer_nanosleep(&tu, rmtp ? &rmt : NULL, HRTIMER_MODE_REL,
--                              CLOCK_MONOTONIC);
-+      oldfs = get_fs();
-+      set_fs(KERNEL_DS);
-+      ret = hrtimer_nanosleep(&tu,
-+                              rmtp ? (struct timespec __user *)&rmt : NULL,
-+                              HRTIMER_MODE_REL, CLOCK_MONOTONIC);
-+      set_fs(oldfs);
--      if (ret && rmtp) {
--              if (put_compat_timespec(&rmt, rmtp))
-+      if (ret) {
-+              struct restart_block *restart
-+                      = &current_thread_info()->restart_block;
-+
-+              restart->fn = compat_nanosleep_restart;
-+              restart->arg1 = (unsigned long)rmtp;
-+
-+              if (rmtp && put_compat_timespec(&rmt, rmtp))
-                       return -EFAULT;
-       }
-diff -Nurd linux-2.6.24/kernel/futex.c linux-2.6.24-oxe810/kernel/futex.c
---- linux-2.6.24/kernel/futex.c        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/kernel/futex.c 2008-06-11 17:43:47.000000000 +0200
-@@ -60,6 +60,8 @@
- #include "rtmutex_common.h"
-+int __read_mostly futex_cmpxchg_enabled;
-+
- #define FUTEX_HASHBITS (CONFIG_BASE_SMALL ? 4 : 8)
- /*
-@@ -466,6 +468,8 @@
-       struct futex_hash_bucket *hb;
-       union futex_key key;
-+      if (!futex_cmpxchg_enabled)
-+              return;
-       /*
-        * We are a ZOMBIE and nobody can enqueue itself on
-        * pi_state_list anymore, but we have to be careful
-@@ -1854,6 +1858,8 @@
- sys_set_robust_list(struct robust_list_head __user *head,
-                   size_t len)
- {
-+      if (!futex_cmpxchg_enabled)
-+              return -ENOSYS;
-       /*
-        * The kernel knows only one size for now:
-        */
-@@ -1878,6 +1884,9 @@
-       struct robust_list_head __user *head;
-       unsigned long ret;
-+      if (!futex_cmpxchg_enabled)
-+              return -ENOSYS;
-+
-       if (!pid)
-               head = current->robust_list;
-       else {
-@@ -1980,6 +1989,9 @@
-       unsigned long futex_offset;
-       int rc;
-+      if (!futex_cmpxchg_enabled)
-+              return;
-+
-       /*
-        * Fetch the list head (which was registered earlier, via
-        * sys_set_robust_list()):
-@@ -2034,7 +2046,7 @@
- long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,
-               u32 __user *uaddr2, u32 val2, u32 val3)
- {
--      int ret;
-+      int ret = -ENOSYS;
-       int cmd = op & FUTEX_CMD_MASK;
-       struct rw_semaphore *fshared = NULL;
-@@ -2062,13 +2074,16 @@
-               ret = futex_wake_op(uaddr, fshared, uaddr2, val, val2, val3);
-               break;
-       case FUTEX_LOCK_PI:
--              ret = futex_lock_pi(uaddr, fshared, val, timeout, 0);
-+              if (futex_cmpxchg_enabled)
-+                      ret = futex_lock_pi(uaddr, fshared, val, timeout, 0);
-               break;
-       case FUTEX_UNLOCK_PI:
--              ret = futex_unlock_pi(uaddr, fshared);
-+              if (futex_cmpxchg_enabled)
-+                      ret = futex_unlock_pi(uaddr, fshared);
-               break;
-       case FUTEX_TRYLOCK_PI:
--              ret = futex_lock_pi(uaddr, fshared, 0, timeout, 1);
-+              if (futex_cmpxchg_enabled)
-+                      ret = futex_lock_pi(uaddr, fshared, 0, timeout, 1);
-               break;
-       default:
-               ret = -ENOSYS;
-@@ -2094,7 +2109,7 @@
-               t = timespec_to_ktime(ts);
-               if (cmd == FUTEX_WAIT)
--                      t = ktime_add(ktime_get(), t);
-+                      t = ktime_add_safe(ktime_get(), t);
-               tp = &t;
-       }
-       /*
-@@ -2123,8 +2138,29 @@
- static int __init init(void)
- {
--      int i = register_filesystem(&futex_fs_type);
-+      u32 curval;
-+      int i;
-+
-+      /*
-+       * This will fail and we want it. Some arch implementations do
-+       * runtime detection of the futex_atomic_cmpxchg_inatomic()
-+       * functionality. We want to know that before we call in any
-+       * of the complex code paths. Also we want to prevent
-+       * registration of robust lists in that case. NULL is
-+       * guaranteed to fault and we get -EFAULT on functional
-+       * implementation, the non functional ones will return
-+       * -ENOSYS.
-+       */
-+      curval = cmpxchg_futex_value_locked(NULL, 0, 0);
-+      if (curval == -EFAULT)
-+              futex_cmpxchg_enabled = 1;
-+      for (i = 0; i < ARRAY_SIZE(futex_queues); i++) {
-+              plist_head_init(&futex_queues[i].chain, &futex_queues[i].lock);
-+              spin_lock_init(&futex_queues[i].lock);
-+      }
-+
-+      i = register_filesystem(&futex_fs_type);
-       if (i)
-               return i;
-@@ -2134,10 +2170,6 @@
-               return PTR_ERR(futex_mnt);
-       }
--      for (i = 0; i < ARRAY_SIZE(futex_queues); i++) {
--              plist_head_init(&futex_queues[i].chain, &futex_queues[i].lock);
--              spin_lock_init(&futex_queues[i].lock);
--      }
-       return 0;
- }
- __initcall(init);
-diff -Nurd linux-2.6.24/kernel/futex_compat.c linux-2.6.24-oxe810/kernel/futex_compat.c
---- linux-2.6.24/kernel/futex_compat.c 2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/kernel/futex_compat.c  2008-06-11 17:43:47.000000000 +0200
-@@ -54,6 +54,9 @@
-       compat_long_t futex_offset;
-       int rc;
-+      if (!futex_cmpxchg_enabled)
-+              return;
-+
-       /*
-        * Fetch the list head (which was registered earlier, via
-        * sys_set_robust_list()):
-@@ -115,6 +118,9 @@
- compat_sys_set_robust_list(struct compat_robust_list_head __user *head,
-                          compat_size_t len)
- {
-+      if (!futex_cmpxchg_enabled)
-+              return -ENOSYS;
-+
-       if (unlikely(len != sizeof(*head)))
-               return -EINVAL;
-@@ -130,6 +136,9 @@
-       struct compat_robust_list_head __user *head;
-       unsigned long ret;
-+      if (!futex_cmpxchg_enabled)
-+              return -ENOSYS;
-+
-       if (!pid)
-               head = current->compat_robust_list;
-       else {
-@@ -175,7 +184,7 @@
-               t = timespec_to_ktime(ts);
-               if (cmd == FUTEX_WAIT)
--                      t = ktime_add(ktime_get(), t);
-+                      t = ktime_add_safe(ktime_get(), t);
-               tp = &t;
-       }
-       if (cmd == FUTEX_REQUEUE || cmd == FUTEX_CMP_REQUEUE)
-diff -Nurd linux-2.6.24/kernel/hrtimer.c linux-2.6.24-oxe810/kernel/hrtimer.c
---- linux-2.6.24/kernel/hrtimer.c      2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/kernel/hrtimer.c       2008-06-11 17:43:47.000000000 +0200
-@@ -325,6 +325,24 @@
- }
- #endif /* BITS_PER_LONG >= 64 */
-+/*
-+ * Add two ktime values and do a safety check for overflow:
-+ */
-+
-+ktime_t ktime_add_safe(const ktime_t lhs, const ktime_t rhs)
-+{
-+      ktime_t res = ktime_add(lhs, rhs);
-+
-+      /*
-+       * We use KTIME_SEC_MAX here, the maximum timeout which we can
-+       * return to user space in a timespec:
-+       */
-+      if (res.tv64 < 0 || res.tv64 < lhs.tv64 || res.tv64 < rhs.tv64)
-+              res = ktime_set(KTIME_SEC_MAX, 0);
-+
-+      return res;
-+}
-+
- /* High resolution timer related functions */
- #ifdef CONFIG_HIGH_RES_TIMERS
-@@ -409,6 +427,8 @@
-       ktime_t expires = ktime_sub(timer->expires, base->offset);
-       int res;
-+      WARN_ON_ONCE(timer->expires.tv64 < 0);
-+
-       /*
-        * When the callback is running, we do not reprogram the clock event
-        * device. The timer callback is either running on a different CPU or
-@@ -419,6 +439,15 @@
-       if (hrtimer_callback_running(timer))
-               return 0;
-+      /*
-+       * CLOCK_REALTIME timer might be requested with an absolute
-+       * expiry time which is less than base->offset. Nothing wrong
-+       * about that, just avoid to call into the tick code, which
-+       * has now objections against negative expiry values.
-+       */
-+      if (expires.tv64 < 0)
-+              return -ETIME;
-+
-       if (expires.tv64 >= expires_next->tv64)
-               return 0;
-@@ -682,13 +711,7 @@
-                */
-               orun++;
-       }
--      timer->expires = ktime_add(timer->expires, interval);
--      /*
--       * Make sure, that the result did not wrap with a very large
--       * interval.
--       */
--      if (timer->expires.tv64 < 0)
--              timer->expires = ktime_set(KTIME_SEC_MAX, 0);
-+      timer->expires = ktime_add_safe(timer->expires, interval);
-       return orun;
- }
-@@ -839,7 +862,7 @@
-       new_base = switch_hrtimer_base(timer, base);
-       if (mode == HRTIMER_MODE_REL) {
--              tim = ktime_add(tim, new_base->get_time());
-+              tim = ktime_add_safe(tim, new_base->get_time());
-               /*
-                * CONFIG_TIME_LOW_RES is a temporary way for architectures
-                * to signal that they simply return xtime in
-@@ -848,16 +871,8 @@
-                * timeouts. This will go away with the GTOD framework.
-                */
- #ifdef CONFIG_TIME_LOW_RES
--              tim = ktime_add(tim, base->resolution);
-+              tim = ktime_add_safe(tim, base->resolution);
- #endif
--              /*
--               * Careful here: User space might have asked for a
--               * very long sleep, so the add above might result in a
--               * negative number, which enqueues the timer in front
--               * of the queue.
--               */
--              if (tim.tv64 < 0)
--                      tim.tv64 = KTIME_MAX;
-       }
-       timer->expires = tim;
-@@ -1291,11 +1306,26 @@
-       return t->task == NULL;
- }
-+static int update_rmtp(struct hrtimer *timer, struct timespec __user *rmtp)
-+{
-+      struct timespec rmt;
-+      ktime_t rem;
-+
-+      rem = ktime_sub(timer->expires, timer->base->get_time());
-+      if (rem.tv64 <= 0)
-+              return 0;
-+      rmt = ktime_to_timespec(rem);
-+
-+      if (copy_to_user(rmtp, &rmt, sizeof(*rmtp)))
-+              return -EFAULT;
-+
-+      return 1;
-+}
-+
- long __sched hrtimer_nanosleep_restart(struct restart_block *restart)
- {
-       struct hrtimer_sleeper t;
--      struct timespec *rmtp;
--      ktime_t time;
-+      struct timespec __user  *rmtp;
-       restart->fn = do_no_restart_syscall;
-@@ -1305,12 +1335,11 @@
-       if (do_nanosleep(&t, HRTIMER_MODE_ABS))
-               return 0;
--      rmtp = (struct timespec *)restart->arg1;
-+      rmtp = (struct timespec __user *)restart->arg1;
-       if (rmtp) {
--              time = ktime_sub(t.timer.expires, t.timer.base->get_time());
--              if (time.tv64 <= 0)
--                      return 0;
--              *rmtp = ktime_to_timespec(time);
-+              int ret = update_rmtp(&t.timer, rmtp);
-+              if (ret <= 0)
-+                      return ret;
-       }
-       restart->fn = hrtimer_nanosleep_restart;
-@@ -1319,12 +1348,11 @@
-       return -ERESTART_RESTARTBLOCK;
- }
--long hrtimer_nanosleep(struct timespec *rqtp, struct timespec *rmtp,
-+long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
-                      const enum hrtimer_mode mode, const clockid_t clockid)
- {
-       struct restart_block *restart;
-       struct hrtimer_sleeper t;
--      ktime_t rem;
-       hrtimer_init(&t.timer, clockid, mode);
-       t.timer.expires = timespec_to_ktime(*rqtp);
-@@ -1336,10 +1364,9 @@
-               return -ERESTARTNOHAND;
-       if (rmtp) {
--              rem = ktime_sub(t.timer.expires, t.timer.base->get_time());
--              if (rem.tv64 <= 0)
--                      return 0;
--              *rmtp = ktime_to_timespec(rem);
-+              int ret = update_rmtp(&t.timer, rmtp);
-+              if (ret <= 0)
-+                      return ret;
-       }
-       restart = &current_thread_info()->restart_block;
-@@ -1355,8 +1382,7 @@
- asmlinkage long
- sys_nanosleep(struct timespec __user *rqtp, struct timespec __user *rmtp)
- {
--      struct timespec tu, rmt;
--      int ret;
-+      struct timespec tu;
-       if (copy_from_user(&tu, rqtp, sizeof(tu)))
-               return -EFAULT;
-@@ -1364,15 +1390,7 @@
-       if (!timespec_valid(&tu))
-               return -EINVAL;
--      ret = hrtimer_nanosleep(&tu, rmtp ? &rmt : NULL, HRTIMER_MODE_REL,
--                              CLOCK_MONOTONIC);
--
--      if (ret && rmtp) {
--              if (copy_to_user(rmtp, &rmt, sizeof(*rmtp)))
--                      return -EFAULT;
--      }
--
--      return ret;
-+      return hrtimer_nanosleep(&tu, rmtp, HRTIMER_MODE_REL, CLOCK_MONOTONIC);
- }
- /*
-diff -Nurd linux-2.6.24/kernel/irq/chip.c linux-2.6.24-oxe810/kernel/irq/chip.c
---- linux-2.6.24/kernel/irq/chip.c     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/kernel/irq/chip.c      2008-06-11 17:43:44.000000000 +0200
-@@ -246,6 +246,17 @@
- }
- /*
-+ * default shutdown function
-+ */
-+static void default_shutdown(unsigned int irq)
-+{
-+      struct irq_desc *desc = irq_desc + irq;
-+
-+      desc->chip->mask(irq);
-+      desc->status |= IRQ_MASKED;
-+}
-+
-+/*
-  * Fixup enable/disable function pointers
-  */
- void irq_chip_set_defaults(struct irq_chip *chip)
-@@ -256,8 +267,15 @@
-               chip->disable = default_disable;
-       if (!chip->startup)
-               chip->startup = default_startup;
-+      /*
-+       * We use chip->disable, when the user provided its own. When
-+       * we have default_disable set for chip->disable, then we need
-+       * to use default_shutdown, otherwise the irq line is not
-+       * disabled on free_irq():
-+       */
-       if (!chip->shutdown)
--              chip->shutdown = chip->disable;
-+              chip->shutdown = chip->disable != default_disable ?
-+                      chip->disable : default_shutdown;
-       if (!chip->name)
-               chip->name = chip->typename;
-       if (!chip->end)
-@@ -589,3 +607,39 @@
-       set_irq_chip(irq, chip);
-       __set_irq_handler(irq, handle, 0, name);
- }
-+
-+void __init set_irq_noprobe(unsigned int irq)
-+{
-+      struct irq_desc *desc;
-+      unsigned long flags;
-+
-+      if (irq >= NR_IRQS) {
-+              printk(KERN_ERR "Trying to mark IRQ%d non-probeable\n", irq);
-+
-+              return;
-+      }
-+
-+      desc = irq_desc + irq;
-+
-+      spin_lock_irqsave(&desc->lock, flags);
-+      desc->status |= IRQ_NOPROBE;
-+      spin_unlock_irqrestore(&desc->lock, flags);
-+}
-+
-+void __init set_irq_probe(unsigned int irq)
-+{
-+      struct irq_desc *desc;
-+      unsigned long flags;
-+
-+      if (irq >= NR_IRQS) {
-+              printk(KERN_ERR "Trying to mark IRQ%d probeable\n", irq);
-+
-+              return;
-+      }
-+
-+      desc = irq_desc + irq;
-+
-+      spin_lock_irqsave(&desc->lock, flags);
-+      desc->status &= ~IRQ_NOPROBE;
-+      spin_unlock_irqrestore(&desc->lock, flags);
-+}
-diff -Nurd linux-2.6.24/kernel/posix-timers.c linux-2.6.24-oxe810/kernel/posix-timers.c
---- linux-2.6.24/kernel/posix-timers.c 2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/kernel/posix-timers.c  2008-06-11 17:43:47.000000000 +0200
-@@ -766,9 +766,11 @@
-       /* SIGEV_NONE timers are not queued ! See common_timer_get */
-       if (((timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE)) {
-               /* Setup correct expiry time for relative timers */
--              if (mode == HRTIMER_MODE_REL)
--                      timer->expires = ktime_add(timer->expires,
--                                                 timer->base->get_time());
-+              if (mode == HRTIMER_MODE_REL) {
-+                      timer->expires =
-+                              ktime_add_safe(timer->expires,
-+                                             timer->base->get_time());
-+              }
-               return 0;
-       }
-@@ -981,20 +983,9 @@
- static int common_nsleep(const clockid_t which_clock, int flags,
-                        struct timespec *tsave, struct timespec __user *rmtp)
- {
--      struct timespec rmt;
--      int ret;
--
--      ret = hrtimer_nanosleep(tsave, rmtp ? &rmt : NULL,
--                              flags & TIMER_ABSTIME ?
--                              HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
--                              which_clock);
--
--      if (ret && rmtp) {
--              if (copy_to_user(rmtp, &rmt, sizeof(*rmtp)))
--                      return -EFAULT;
--      }
--
--      return ret;
-+      return hrtimer_nanosleep(tsave, rmtp, flags & TIMER_ABSTIME ?
-+                               HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
-+                               which_clock);
- }
- asmlinkage long
-diff -Nurd linux-2.6.24/kernel/printk.c linux-2.6.24-oxe810/kernel/printk.c
---- linux-2.6.24/kernel/printk.c       2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/kernel/printk.c        2008-06-11 17:43:47.000000000 +0200
+diff -Nurd linux-2.6.24.4/kernel/printk.c linux-2.6.24/kernel/printk.c
+--- linux-2.6.24.4/kernel/printk.c     2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/kernel/printk.c       2010-01-14 14:01:15.000000000 +0100
 @@ -625,6 +625,11 @@
        return r;
  }
@@ -54172,145 +48932,9 @@ diff -Nurd linux-2.6.24/kernel/printk.c linux-2.6.24-oxe810/kernel/printk.c
        /*
         * Copy the output into log_buf.  If the caller didn't provide
         * appropriate log level tags, we insert them here
-diff -Nurd linux-2.6.24/kernel/relay.c linux-2.6.24-oxe810/kernel/relay.c
---- linux-2.6.24/kernel/relay.c        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/kernel/relay.c 2008-06-11 17:43:47.000000000 +0200
-@@ -92,6 +92,7 @@
-               return -EINVAL;
-       vma->vm_ops = &relay_file_mmap_ops;
-+      vma->vm_flags |= VM_DONTEXPAND;
-       vma->vm_private_data = buf;
-       buf->chan->cb->buf_mapped(buf, filp);
-@@ -1071,7 +1072,7 @@
-                              unsigned int flags,
-                              int *nonpad_ret)
- {
--      unsigned int pidx, poff, total_len, subbuf_pages, ret;
-+      unsigned int pidx, poff, total_len, subbuf_pages, nr_pages, ret;
-       struct rchan_buf *rbuf = in->private_data;
-       unsigned int subbuf_size = rbuf->chan->subbuf_size;
-       uint64_t pos = (uint64_t) *ppos;
-@@ -1102,8 +1103,9 @@
-       subbuf_pages = rbuf->chan->alloc_size >> PAGE_SHIFT;
-       pidx = (read_start / PAGE_SIZE) % subbuf_pages;
-       poff = read_start & ~PAGE_MASK;
-+      nr_pages = min_t(unsigned int, subbuf_pages, PIPE_BUFFERS);
--      for (total_len = 0; spd.nr_pages < subbuf_pages; spd.nr_pages++) {
-+      for (total_len = 0; spd.nr_pages < nr_pages; spd.nr_pages++) {
-               unsigned int this_len, this_end, private;
-               unsigned int cur_pos = read_start + total_len;
-diff -Nurd linux-2.6.24/kernel/sched.c linux-2.6.24-oxe810/kernel/sched.c
---- linux-2.6.24/kernel/sched.c        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/kernel/sched.c 2008-06-11 17:43:47.000000000 +0200
-@@ -4028,11 +4028,10 @@
-       oldprio = p->prio;
-       on_rq = p->se.on_rq;
-       running = task_current(rq, p);
--      if (on_rq) {
-+      if (on_rq)
-               dequeue_task(rq, p, 0);
--              if (running)
--                      p->sched_class->put_prev_task(rq, p);
--      }
-+      if (running)
-+              p->sched_class->put_prev_task(rq, p);
-       if (rt_prio(prio))
-               p->sched_class = &rt_sched_class;
-@@ -4041,9 +4040,9 @@
-       p->prio = prio;
-+      if (running)
-+              p->sched_class->set_curr_task(rq);
-       if (on_rq) {
--              if (running)
--                      p->sched_class->set_curr_task(rq);
-               enqueue_task(rq, p, 0);
-               /*
-                * Reschedule if we are currently running on this runqueue and
-@@ -4339,18 +4338,17 @@
-       update_rq_clock(rq);
-       on_rq = p->se.on_rq;
-       running = task_current(rq, p);
--      if (on_rq) {
-+      if (on_rq)
-               deactivate_task(rq, p, 0);
--              if (running)
--                      p->sched_class->put_prev_task(rq, p);
--      }
-+      if (running)
-+              p->sched_class->put_prev_task(rq, p);
-       oldprio = p->prio;
-       __setscheduler(rq, p, policy, param->sched_priority);
-+      if (running)
-+              p->sched_class->set_curr_task(rq);
-       if (on_rq) {
--              if (running)
--                      p->sched_class->set_curr_task(rq);
-               activate_task(rq, p, 0);
-               /*
-                * Reschedule if we are currently running on this runqueue and
-@@ -7110,19 +7108,17 @@
-       running = task_current(rq, tsk);
-       on_rq = tsk->se.on_rq;
--      if (on_rq) {
-+      if (on_rq)
-               dequeue_task(rq, tsk, 0);
--              if (unlikely(running))
--                      tsk->sched_class->put_prev_task(rq, tsk);
--      }
-+      if (unlikely(running))
-+              tsk->sched_class->put_prev_task(rq, tsk);
-       set_task_cfs_rq(tsk, task_cpu(tsk));
--      if (on_rq) {
--              if (unlikely(running))
--                      tsk->sched_class->set_curr_task(rq);
-+      if (unlikely(running))
-+              tsk->sched_class->set_curr_task(rq);
-+      if (on_rq)
-               enqueue_task(rq, tsk, 0);
--      }
- done:
-       task_rq_unlock(rq, &flags);
-diff -Nurd linux-2.6.24/kernel/sched_fair.c linux-2.6.24-oxe810/kernel/sched_fair.c
---- linux-2.6.24/kernel/sched_fair.c   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/kernel/sched_fair.c    2008-06-11 17:43:47.000000000 +0200
-@@ -511,7 +511,7 @@
-       if (!initial) {
-               /* sleeps upto a single latency don't count. */
--              if (sched_feat(NEW_FAIR_SLEEPERS) && entity_is_task(se))
-+              if (sched_feat(NEW_FAIR_SLEEPERS))
-                       vruntime -= sysctl_sched_latency;
-               /* ensure we never gain time by being placed backwards. */
-@@ -867,7 +867,11 @@
-       }
-       gran = sysctl_sched_wakeup_granularity;
--      if (unlikely(se->load.weight != NICE_0_LOAD))
-+      /*
-+       * More easily preempt - nice tasks, while not making
-+       * it harder for + nice tasks.
-+       */
-+      if (unlikely(se->load.weight > NICE_0_LOAD))
-               gran = calc_delta_fair(gran, &se->load);
-       if (pse->vruntime + gran < se->vruntime)
-diff -Nurd linux-2.6.24/kernel/softirq.c linux-2.6.24-oxe810/kernel/softirq.c
---- linux-2.6.24/kernel/softirq.c      2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/kernel/softirq.c       2008-06-11 17:43:47.000000000 +0200
+diff -Nurd linux-2.6.24.4/kernel/softirq.c linux-2.6.24/kernel/softirq.c
+--- linux-2.6.24.4/kernel/softirq.c    2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/kernel/softirq.c      2010-01-14 14:01:15.000000000 +0100
 @@ -72,7 +72,7 @@
  {
        unsigned long flags;
@@ -54332,30 +48956,9 @@ diff -Nurd linux-2.6.24/kernel/softirq.c linux-2.6.24-oxe810/kernel/softirq.c
  
  #ifdef CONFIG_TRACE_IRQFLAGS
        local_irq_save(flags);
-diff -Nurd linux-2.6.24/kernel/sysctl.c linux-2.6.24-oxe810/kernel/sysctl.c
---- linux-2.6.24/kernel/sysctl.c       2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/kernel/sysctl.c        2008-06-11 17:43:47.000000000 +0200
-@@ -306,7 +306,7 @@
-               .procname       = "sched_nr_migrate",
-               .data           = &sysctl_sched_nr_migrate,
-               .maxlen         = sizeof(unsigned int),
--              .mode           = 644,
-+              .mode           = 0644,
-               .proc_handler   = &proc_dointvec,
-       },
- #endif
-@@ -910,7 +910,7 @@
-               .data           = &nr_overcommit_huge_pages,
-               .maxlen         = sizeof(nr_overcommit_huge_pages),
-               .mode           = 0644,
--              .proc_handler   = &proc_doulongvec_minmax,
-+              .proc_handler   = &hugetlb_overcommit_handler,
-       },
- #endif
-       {
-diff -Nurd linux-2.6.24/mm/filemap.c linux-2.6.24-oxe810/mm/filemap.c
---- linux-2.6.24/mm/filemap.c  2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/mm/filemap.c   2008-06-11 17:47:28.000000000 +0200
+diff -Nurd linux-2.6.24.4/mm/filemap.c linux-2.6.24/mm/filemap.c
+--- linux-2.6.24.4/mm/filemap.c        2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/mm/filemap.c  2010-01-14 14:01:15.000000000 +0100
 @@ -884,12 +884,31 @@
        unsigned int prev_offset;
        int error;
@@ -54678,149 +49281,9 @@ diff -Nurd linux-2.6.24/mm/filemap.c linux-2.6.24-oxe810/mm/filemap.c
  static ssize_t
  do_readahead(struct address_space *mapping, struct file *filp,
             pgoff_t index, unsigned long nr)
-@@ -1725,17 +1893,27 @@
- }
- EXPORT_SYMBOL(iov_iter_copy_from_user);
--static void __iov_iter_advance_iov(struct iov_iter *i, size_t bytes)
-+void iov_iter_advance(struct iov_iter *i, size_t bytes)
- {
-+      BUG_ON(i->count < bytes);
-+
-       if (likely(i->nr_segs == 1)) {
-               i->iov_offset += bytes;
-+              i->count -= bytes;
-       } else {
-               const struct iovec *iov = i->iov;
-               size_t base = i->iov_offset;
--              while (bytes) {
--                      int copy = min(bytes, iov->iov_len - base);
-+              /*
-+               * The !iov->iov_len check ensures we skip over unlikely
-+               * zero-length segments (without overruning the iovec).
-+               */
-+              while (bytes || unlikely(!iov->iov_len && i->count)) {
-+                      int copy;
-+                      copy = min(bytes, iov->iov_len - base);
-+                      BUG_ON(!i->count || i->count < copy);
-+                      i->count -= copy;
-                       bytes -= copy;
-                       base += copy;
-                       if (iov->iov_len == base) {
-@@ -1747,14 +1925,6 @@
-               i->iov_offset = base;
-       }
- }
--
--void iov_iter_advance(struct iov_iter *i, size_t bytes)
--{
--      BUG_ON(i->count < bytes);
--
--      __iov_iter_advance_iov(i, bytes);
--      i->count -= bytes;
--}
- EXPORT_SYMBOL(iov_iter_advance);
- /*
-@@ -2251,6 +2421,7 @@
-               cond_resched();
-+              iov_iter_advance(i, copied);
-               if (unlikely(copied == 0)) {
-                       /*
-                        * If we were unable to copy any data at all, we must
-@@ -2264,7 +2435,6 @@
-                                               iov_iter_single_seg_count(i));
-                       goto again;
-               }
--              iov_iter_advance(i, copied);
-               pos += copied;
-               written += copied;
-diff -Nurd linux-2.6.24/mm/fremap.c linux-2.6.24-oxe810/mm/fremap.c
---- linux-2.6.24/mm/fremap.c   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/mm/fremap.c    2008-06-11 17:47:28.000000000 +0200
-@@ -190,10 +190,13 @@
-                */
-               if (mapping_cap_account_dirty(mapping)) {
-                       unsigned long addr;
-+                      struct file *file = vma->vm_file;
-                       flags &= MAP_NONBLOCK;
--                      addr = mmap_region(vma->vm_file, start, size,
-+                      get_file(file);
-+                      addr = mmap_region(file, start, size,
-                                       flags, vma->vm_flags, pgoff, 1);
-+                      fput(file);
-                       if (IS_ERR_VALUE(addr)) {
-                               err = addr;
-                       } else {
-diff -Nurd linux-2.6.24/mm/hugetlb.c linux-2.6.24-oxe810/mm/hugetlb.c
---- linux-2.6.24/mm/hugetlb.c  2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/mm/hugetlb.c   2008-06-11 17:47:28.000000000 +0200
-@@ -119,6 +119,7 @@
-       struct address_space *mapping;
-       mapping = (struct address_space *) page_private(page);
-+      set_page_private(page, 0);
-       BUG_ON(page_count(page));
-       INIT_LIST_HEAD(&page->lru);
-@@ -133,7 +134,6 @@
-       spin_unlock(&hugetlb_lock);
-       if (mapping)
-               hugetlb_put_quota(mapping, 1);
--      set_page_private(page, 0);
- }
- /*
-@@ -605,6 +605,16 @@
-       return 0;
- }
-+int hugetlb_overcommit_handler(struct ctl_table *table, int write,
-+                      struct file *file, void __user *buffer,
-+                      size_t *length, loff_t *ppos)
-+{
-+      spin_lock(&hugetlb_lock);
-+      proc_doulongvec_minmax(table, write, file, buffer, length, ppos);
-+      spin_unlock(&hugetlb_lock);
-+      return 0;
-+}
-+
- #endif /* CONFIG_SYSCTL */
- int hugetlb_report_meminfo(char *buf)
-diff -Nurd linux-2.6.24/mm/memory.c linux-2.6.24-oxe810/mm/memory.c
---- linux-2.6.24/mm/memory.c   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/mm/memory.c    2008-06-11 17:47:28.000000000 +0200
-@@ -980,6 +980,8 @@
-       int i;
-       unsigned int vm_flags;
-+      if (len <= 0)
-+              return 0;
-       /* 
-        * Require read or write permissions.
-        * If 'force' is set, we only require the "MAY" flags.
-diff -Nurd linux-2.6.24/mm/mmap.c linux-2.6.24-oxe810/mm/mmap.c
---- linux-2.6.24/mm/mmap.c     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/mm/mmap.c      2008-06-11 17:47:28.000000000 +0200
-@@ -2215,7 +2215,7 @@
-       vma->vm_start = addr;
-       vma->vm_end = addr + len;
--      vma->vm_flags = vm_flags | mm->def_flags;
-+      vma->vm_flags = vm_flags | mm->def_flags | VM_DONTEXPAND;
-       vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
-       vma->vm_ops = &special_mapping_vmops;
-diff -Nurd linux-2.6.24/mm/shmem.c linux-2.6.24-oxe810/mm/shmem.c
---- linux-2.6.24/mm/shmem.c    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/mm/shmem.c     2008-06-11 17:47:28.000000000 +0200
+diff -Nurd linux-2.6.24.4/mm/shmem.c linux-2.6.24/mm/shmem.c
+--- linux-2.6.24.4/mm/shmem.c  2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/mm/shmem.c    2010-01-14 14:01:15.000000000 +0100
 @@ -1681,7 +1681,7 @@
                 * "pos" here (the actor routine has to update the user buffer
                 * pointers and the remaining count).
@@ -54830,312 +49293,9 @@ diff -Nurd linux-2.6.24/mm/shmem.c linux-2.6.24-oxe810/mm/shmem.c
                offset += ret;
                index += offset >> PAGE_CACHE_SHIFT;
                offset &= ~PAGE_CACHE_MASK;
-diff -Nurd linux-2.6.24/mm/slab.c linux-2.6.24-oxe810/mm/slab.c
---- linux-2.6.24/mm/slab.c     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/mm/slab.c      2008-06-11 17:47:28.000000000 +0200
-@@ -304,11 +304,11 @@
- /*
-  * Need this for bootstrapping a per node allocator.
-  */
--#define NUM_INIT_LISTS (2 * MAX_NUMNODES + 1)
-+#define NUM_INIT_LISTS (3 * MAX_NUMNODES)
- struct kmem_list3 __initdata initkmem_list3[NUM_INIT_LISTS];
- #define       CACHE_CACHE 0
--#define       SIZE_AC 1
--#define       SIZE_L3 (1 + MAX_NUMNODES)
-+#define       SIZE_AC MAX_NUMNODES
-+#define       SIZE_L3 (2 * MAX_NUMNODES)
- static int drain_freelist(struct kmem_cache *cache,
-                       struct kmem_list3 *l3, int tofree);
-@@ -1410,6 +1410,22 @@
- }
- /*
-+ * For setting up all the kmem_list3s for cache whose buffer_size is same as
-+ * size of kmem_list3.
-+ */
-+static void __init set_up_list3s(struct kmem_cache *cachep, int index)
-+{
-+      int node;
-+
-+      for_each_online_node(node) {
-+              cachep->nodelists[node] = &initkmem_list3[index + node];
-+              cachep->nodelists[node]->next_reap = jiffies +
-+                  REAPTIMEOUT_LIST3 +
-+                  ((unsigned long)cachep) % REAPTIMEOUT_LIST3;
-+      }
-+}
-+
-+/*
-  * Initialisation.  Called after the page allocator have been initialised and
-  * before smp_init().
-  */
-@@ -1432,6 +1448,7 @@
-               if (i < MAX_NUMNODES)
-                       cache_cache.nodelists[i] = NULL;
-       }
-+      set_up_list3s(&cache_cache, CACHE_CACHE);
-       /*
-        * Fragmentation resistance on low memory - only use bigger
-@@ -1587,10 +1604,9 @@
-       {
-               int nid;
--              /* Replace the static kmem_list3 structures for the boot cpu */
--              init_list(&cache_cache, &initkmem_list3[CACHE_CACHE], node);
--
-               for_each_online_node(nid) {
-+                      init_list(&cache_cache, &initkmem_list3[CACHE_CACHE], nid);
-+
-                       init_list(malloc_sizes[INDEX_AC].cs_cachep,
-                                 &initkmem_list3[SIZE_AC + nid], nid);
-@@ -1960,22 +1976,6 @@
-       }
- }
--/*
-- * For setting up all the kmem_list3s for cache whose buffer_size is same as
-- * size of kmem_list3.
-- */
--static void __init set_up_list3s(struct kmem_cache *cachep, int index)
--{
--      int node;
--
--      for_each_online_node(node) {
--              cachep->nodelists[node] = &initkmem_list3[index + node];
--              cachep->nodelists[node]->next_reap = jiffies +
--                  REAPTIMEOUT_LIST3 +
--                  ((unsigned long)cachep) % REAPTIMEOUT_LIST3;
--      }
--}
--
- static void __kmem_cache_destroy(struct kmem_cache *cachep)
- {
-       int i;
-@@ -2099,7 +2099,7 @@
-                       g_cpucache_up = PARTIAL_L3;
-               } else {
-                       int node;
--                      for_each_node_state(node, N_NORMAL_MEMORY) {
-+                      for_each_online_node(node) {
-                               cachep->nodelists[node] =
-                                   kmalloc_node(sizeof(struct kmem_list3),
-                                               GFP_KERNEL, node);
-@@ -2961,11 +2961,10 @@
-       struct array_cache *ac;
-       int node;
--      node = numa_node_id();
--
-+retry:
-       check_irq_off();
-+      node = numa_node_id();
-       ac = cpu_cache_get(cachep);
--retry:
-       batchcount = ac->batchcount;
-       if (!ac->touched && batchcount > BATCHREFILL_LIMIT) {
-               /*
-diff -Nurd linux-2.6.24/mm/slub.c linux-2.6.24-oxe810/mm/slub.c
---- linux-2.6.24/mm/slub.c     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/mm/slub.c      2008-06-11 17:47:28.000000000 +0200
-@@ -2592,6 +2592,7 @@
- void kfree(const void *x)
- {
-       struct page *page;
-+      void *object = (void *)x;
-       if (unlikely(ZERO_OR_NULL_PTR(x)))
-               return;
-@@ -2601,7 +2602,7 @@
-               put_page(page);
-               return;
-       }
--      slab_free(page->slab, page, (void *)x, __builtin_return_address(0));
-+      slab_free(page->slab, page, object, __builtin_return_address(0));
- }
- EXPORT_SYMBOL(kfree);
-diff -Nurd linux-2.6.24/net/bluetooth/hci_sysfs.c linux-2.6.24-oxe810/net/bluetooth/hci_sysfs.c
---- linux-2.6.24/net/bluetooth/hci_sysfs.c     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/net/bluetooth/hci_sysfs.c      2008-06-11 17:46:02.000000000 +0200
-@@ -12,6 +12,8 @@
- #undef  BT_DBG
- #define BT_DBG(D...)
- #endif
-+static struct workqueue_struct *btaddconn;
-+static struct workqueue_struct *btdelconn;
- static inline char *typetostr(int type)
- {
-@@ -279,6 +281,8 @@
-       struct hci_conn *conn = container_of(work, struct hci_conn, work);
-       int i;
-+      flush_workqueue(btdelconn);
-+
-       if (device_add(&conn->dev) < 0) {
-               BT_ERR("Failed to register connection device");
-               return;
-@@ -313,7 +317,7 @@
-       INIT_WORK(&conn->work, add_conn);
--      schedule_work(&conn->work);
-+      queue_work(btaddconn, &conn->work);
- }
- static int __match_tty(struct device *dev, void *data)
-@@ -349,7 +353,7 @@
-       INIT_WORK(&conn->work, del_conn);
--      schedule_work(&conn->work);
-+      queue_work(btdelconn, &conn->work);
- }
- int hci_register_sysfs(struct hci_dev *hdev)
-@@ -398,28 +402,54 @@
- {
-       int err;
-+      btaddconn = create_singlethread_workqueue("btaddconn");
-+      if (!btaddconn) {
-+              err = -ENOMEM;
-+              goto out;
-+      }
-+
-+      btdelconn = create_singlethread_workqueue("btdelconn");
-+      if (!btdelconn) {
-+              err = -ENOMEM;
-+              goto out_del;
-+      }
-+
-       bt_platform = platform_device_register_simple("bluetooth", -1, NULL, 0);
--      if (IS_ERR(bt_platform))
--              return PTR_ERR(bt_platform);
-+      if (IS_ERR(bt_platform)) {
-+              err = PTR_ERR(bt_platform);
-+              goto out_platform;
-+      }
-       err = bus_register(&bt_bus);
--      if (err < 0) {
--              platform_device_unregister(bt_platform);
--              return err;
--      }
-+      if (err < 0)
-+              goto out_bus;
-       bt_class = class_create(THIS_MODULE, "bluetooth");
-       if (IS_ERR(bt_class)) {
--              bus_unregister(&bt_bus);
--              platform_device_unregister(bt_platform);
--              return PTR_ERR(bt_class);
-+              err = PTR_ERR(bt_class);
-+              goto out_class;
-       }
-       return 0;
-+
-+out_class:
-+      bus_unregister(&bt_bus);
-+out_bus:
-+      platform_device_unregister(bt_platform);
-+out_platform:
-+      destroy_workqueue(btdelconn);
-+out_del:
-+      destroy_workqueue(btaddconn);
-+out:
-+      return err;
- }
- void bt_sysfs_cleanup(void)
- {
-+      destroy_workqueue(btaddconn);
-+
-+      destroy_workqueue(btdelconn);
-+
-       class_destroy(bt_class);
-       bus_unregister(&bt_bus);
-diff -Nurd linux-2.6.24/net/bridge/netfilter/ebt_dnat.c linux-2.6.24-oxe810/net/bridge/netfilter/ebt_dnat.c
---- linux-2.6.24/net/bridge/netfilter/ebt_dnat.c       2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/net/bridge/netfilter/ebt_dnat.c        2008-06-11 17:46:12.000000000 +0200
-@@ -20,8 +20,8 @@
- {
-       struct ebt_nat_info *info = (struct ebt_nat_info *)data;
--      if (skb_make_writable(skb, 0))
--              return NF_DROP;
-+      if (!skb_make_writable(skb, 0))
-+              return EBT_DROP;
-       memcpy(eth_hdr(skb)->h_dest, info->mac, ETH_ALEN);
-       return info->target;
-diff -Nurd linux-2.6.24/net/bridge/netfilter/ebt_redirect.c linux-2.6.24-oxe810/net/bridge/netfilter/ebt_redirect.c
---- linux-2.6.24/net/bridge/netfilter/ebt_redirect.c   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/net/bridge/netfilter/ebt_redirect.c    2008-06-11 17:46:12.000000000 +0200
-@@ -21,8 +21,8 @@
- {
-       struct ebt_redirect_info *info = (struct ebt_redirect_info *)data;
--      if (skb_make_writable(skb, 0))
--              return NF_DROP;
-+      if (!skb_make_writable(skb, 0))
-+              return EBT_DROP;
-       if (hooknr != NF_BR_BROUTING)
-               memcpy(eth_hdr(skb)->h_dest,
-diff -Nurd linux-2.6.24/net/bridge/netfilter/ebt_snat.c linux-2.6.24-oxe810/net/bridge/netfilter/ebt_snat.c
---- linux-2.6.24/net/bridge/netfilter/ebt_snat.c       2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/net/bridge/netfilter/ebt_snat.c        2008-06-11 17:46:12.000000000 +0200
-@@ -22,8 +22,8 @@
- {
-       struct ebt_nat_info *info = (struct ebt_nat_info *) data;
--      if (skb_make_writable(skb, 0))
--              return NF_DROP;
-+      if (!skb_make_writable(skb, 0))
-+              return EBT_DROP;
-       memcpy(eth_hdr(skb)->h_source, info->mac, ETH_ALEN);
-       if (!(info->target & NAT_ARP_BIT) &&
-diff -Nurd linux-2.6.24/net/core/dev.c linux-2.6.24-oxe810/net/core/dev.c
---- linux-2.6.24/net/core/dev.c        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/net/core/dev.c 2008-06-11 17:45:57.000000000 +0200
-@@ -1068,8 +1068,6 @@
-        */
-       call_netdevice_notifiers(NETDEV_GOING_DOWN, dev);
--      dev_deactivate(dev);
--
-       clear_bit(__LINK_STATE_START, &dev->state);
-       /* Synchronize to scheduled poll. We cannot touch poll list,
-@@ -1080,6 +1078,8 @@
-        */
-       smp_mb__after_clear_bit(); /* Commit netif_running(). */
-+      dev_deactivate(dev);
-+
-       /*
-        *      Call the device specific close. This cannot fail.
-        *      Only if device is UP
-@@ -2906,7 +2906,7 @@
-               }
-       }
--      da = kmalloc(sizeof(*da), GFP_ATOMIC);
-+      da = kzalloc(sizeof(*da), GFP_ATOMIC);
-       if (da == NULL)
-               return -ENOMEM;
-       memcpy(da->da_addr, addr, alen);
-diff -Nurd linux-2.6.24/net/ipv4/af_inet.c linux-2.6.24-oxe810/net/ipv4/af_inet.c
---- linux-2.6.24/net/ipv4/af_inet.c    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/net/ipv4/af_inet.c     2008-06-11 17:46:09.000000000 +0200
+diff -Nurd linux-2.6.24.4/net/ipv4/af_inet.c linux-2.6.24/net/ipv4/af_inet.c
+--- linux-2.6.24.4/net/ipv4/af_inet.c  2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/net/ipv4/af_inet.c    2010-01-14 14:01:15.000000000 +0100
 @@ -838,6 +838,7 @@
        .recvmsg           = sock_common_recvmsg,
        .mmap              = sock_no_mmap,
@@ -55144,375 +49304,9 @@ diff -Nurd linux-2.6.24/net/ipv4/af_inet.c linux-2.6.24-oxe810/net/ipv4/af_inet.
  #ifdef CONFIG_COMPAT
        .compat_setsockopt = compat_sock_common_setsockopt,
        .compat_getsockopt = compat_sock_common_getsockopt,
-diff -Nurd linux-2.6.24/net/ipv4/fib_hash.c linux-2.6.24-oxe810/net/ipv4/fib_hash.c
---- linux-2.6.24/net/ipv4/fib_hash.c   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/net/ipv4/fib_hash.c    2008-06-11 17:46:09.000000000 +0200
-@@ -434,19 +434,43 @@
-       if (fa && fa->fa_tos == tos &&
-           fa->fa_info->fib_priority == fi->fib_priority) {
--              struct fib_alias *fa_orig;
-+              struct fib_alias *fa_first, *fa_match;
-               err = -EEXIST;
-               if (cfg->fc_nlflags & NLM_F_EXCL)
-                       goto out;
-+              /* We have 2 goals:
-+               * 1. Find exact match for type, scope, fib_info to avoid
-+               * duplicate routes
-+               * 2. Find next 'fa' (or head), NLM_F_APPEND inserts before it
-+               */
-+              fa_match = NULL;
-+              fa_first = fa;
-+              fa = list_entry(fa->fa_list.prev, struct fib_alias, fa_list);
-+              list_for_each_entry_continue(fa, &f->fn_alias, fa_list) {
-+                      if (fa->fa_tos != tos)
-+                              break;
-+                      if (fa->fa_info->fib_priority != fi->fib_priority)
-+                              break;
-+                      if (fa->fa_type == cfg->fc_type &&
-+                          fa->fa_scope == cfg->fc_scope &&
-+                          fa->fa_info == fi) {
-+                              fa_match = fa;
-+                              break;
-+                      }
-+              }
-+
-               if (cfg->fc_nlflags & NLM_F_REPLACE) {
-                       struct fib_info *fi_drop;
-                       u8 state;
--                      if (fi->fib_treeref > 1)
-+                      fa = fa_first;
-+                      if (fa_match) {
-+                              if (fa == fa_match)
-+                                      err = 0;
-                               goto out;
--
-+                      }
-                       write_lock_bh(&fib_hash_lock);
-                       fi_drop = fa->fa_info;
-                       fa->fa_info = fi;
-@@ -469,20 +493,11 @@
-                * uses the same scope, type, and nexthop
-                * information.
-                */
--              fa_orig = fa;
--              fa = list_entry(fa->fa_list.prev, struct fib_alias, fa_list);
--              list_for_each_entry_continue(fa, &f->fn_alias, fa_list) {
--                      if (fa->fa_tos != tos)
--                              break;
--                      if (fa->fa_info->fib_priority != fi->fib_priority)
--                              break;
--                      if (fa->fa_type == cfg->fc_type &&
--                          fa->fa_scope == cfg->fc_scope &&
--                          fa->fa_info == fi)
--                              goto out;
--              }
-+              if (fa_match)
-+                      goto out;
-+
-               if (!(cfg->fc_nlflags & NLM_F_APPEND))
--                      fa = fa_orig;
-+                      fa = fa_first;
-       }
-       err = -ENOENT;
-diff -Nurd linux-2.6.24/net/ipv4/fib_trie.c linux-2.6.24-oxe810/net/ipv4/fib_trie.c
---- linux-2.6.24/net/ipv4/fib_trie.c   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/net/ipv4/fib_trie.c    2008-06-11 17:46:09.000000000 +0200
-@@ -1203,20 +1203,45 @@
-        * and we need to allocate a new one of those as well.
-        */
--      if (fa && fa->fa_info->fib_priority == fi->fib_priority) {
--              struct fib_alias *fa_orig;
-+      if (fa && fa->fa_tos == tos &&
-+          fa->fa_info->fib_priority == fi->fib_priority) {
-+              struct fib_alias *fa_first, *fa_match;
-               err = -EEXIST;
-               if (cfg->fc_nlflags & NLM_F_EXCL)
-                       goto out;
-+              /* We have 2 goals:
-+               * 1. Find exact match for type, scope, fib_info to avoid
-+               * duplicate routes
-+               * 2. Find next 'fa' (or head), NLM_F_APPEND inserts before it
-+               */
-+              fa_match = NULL;
-+              fa_first = fa;
-+              fa = list_entry(fa->fa_list.prev, struct fib_alias, fa_list);
-+              list_for_each_entry_continue(fa, fa_head, fa_list) {
-+                      if (fa->fa_tos != tos)
-+                              break;
-+                      if (fa->fa_info->fib_priority != fi->fib_priority)
-+                              break;
-+                      if (fa->fa_type == cfg->fc_type &&
-+                          fa->fa_scope == cfg->fc_scope &&
-+                          fa->fa_info == fi) {
-+                              fa_match = fa;
-+                              break;
-+                      }
-+              }
-+
-               if (cfg->fc_nlflags & NLM_F_REPLACE) {
-                       struct fib_info *fi_drop;
-                       u8 state;
--                      if (fi->fib_treeref > 1)
-+                      fa = fa_first;
-+                      if (fa_match) {
-+                              if (fa == fa_match)
-+                                      err = 0;
-                               goto out;
--
-+                      }
-                       err = -ENOBUFS;
-                       new_fa = kmem_cache_alloc(fn_alias_kmem, GFP_KERNEL);
-                       if (new_fa == NULL)
-@@ -1228,7 +1253,7 @@
-                       new_fa->fa_type = cfg->fc_type;
-                       new_fa->fa_scope = cfg->fc_scope;
-                       state = fa->fa_state;
--                      new_fa->fa_state &= ~FA_S_ACCESSED;
-+                      new_fa->fa_state = state & ~FA_S_ACCESSED;
-                       list_replace_rcu(&fa->fa_list, &new_fa->fa_list);
-                       alias_free_mem_rcu(fa);
-@@ -1245,20 +1270,11 @@
-                * uses the same scope, type, and nexthop
-                * information.
-                */
--              fa_orig = fa;
--              list_for_each_entry(fa, fa_orig->fa_list.prev, fa_list) {
--                      if (fa->fa_tos != tos)
--                              break;
--                      if (fa->fa_info->fib_priority != fi->fib_priority)
--                              break;
--                      if (fa->fa_type == cfg->fc_type &&
--                          fa->fa_scope == cfg->fc_scope &&
--                          fa->fa_info == fi) {
--                              goto out;
--                      }
--              }
-+              if (fa_match)
-+                      goto out;
-+
-               if (!(cfg->fc_nlflags & NLM_F_APPEND))
--                      fa = fa_orig;
-+                      fa = fa_first;
-       }
-       err = -ENOENT;
-       if (!(cfg->fc_nlflags & NLM_F_CREATE))
-@@ -1614,9 +1630,8 @@
-       pr_debug("Deleting %08x/%d tos=%d t=%p\n", key, plen, tos, t);
-       fa_to_delete = NULL;
--      fa_head = fa->fa_list.prev;
--
--      list_for_each_entry(fa, fa_head, fa_list) {
-+      fa = list_entry(fa->fa_list.prev, struct fib_alias, fa_list);
-+      list_for_each_entry_continue(fa, fa_head, fa_list) {
-               struct fib_info *fi = fa->fa_info;
-               if (fa->fa_tos != tos)
-diff -Nurd linux-2.6.24/net/ipv4/inet_diag.c linux-2.6.24-oxe810/net/ipv4/inet_diag.c
---- linux-2.6.24/net/ipv4/inet_diag.c  2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/net/ipv4/inet_diag.c   2008-06-11 17:46:09.000000000 +0200
-@@ -259,8 +259,10 @@
-       const struct inet_diag_handler *handler;
-       handler = inet_diag_lock_handler(nlh->nlmsg_type);
--      if (!handler)
--              return -ENOENT;
-+      if (IS_ERR(handler)) {
-+              err = PTR_ERR(handler);
-+              goto unlock;
-+      }
-       hashinfo = handler->idiag_hashinfo;
-       err = -EINVAL;
-@@ -708,8 +710,8 @@
-       struct inet_hashinfo *hashinfo;
-       handler = inet_diag_lock_handler(cb->nlh->nlmsg_type);
--      if (!handler)
--              goto no_handler;
-+      if (IS_ERR(handler))
-+              goto unlock;
-       hashinfo = handler->idiag_hashinfo;
-@@ -838,7 +840,6 @@
-       cb->args[2] = num;
- unlock:
-       inet_diag_unlock_handler(handler);
--no_handler:
-       return skb->len;
- }
-diff -Nurd linux-2.6.24/net/ipv4/ip_output.c linux-2.6.24-oxe810/net/ipv4/ip_output.c
---- linux-2.6.24/net/ipv4/ip_output.c  2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/net/ipv4/ip_output.c   2008-06-11 17:46:09.000000000 +0200
-@@ -462,6 +462,7 @@
-       if (skb_shinfo(skb)->frag_list) {
-               struct sk_buff *frag;
-               int first_len = skb_pagelen(skb);
-+              int truesizes = 0;
-               if (first_len - hlen > mtu ||
-                   ((first_len - hlen) & 7) ||
-@@ -485,7 +486,7 @@
-                               sock_hold(skb->sk);
-                               frag->sk = skb->sk;
-                               frag->destructor = sock_wfree;
--                              skb->truesize -= frag->truesize;
-+                              truesizes += frag->truesize;
-                       }
-               }
-@@ -496,6 +497,7 @@
-               frag = skb_shinfo(skb)->frag_list;
-               skb_shinfo(skb)->frag_list = NULL;
-               skb->data_len = first_len - skb_headlen(skb);
-+              skb->truesize -= truesizes;
-               skb->len = first_len;
-               iph->tot_len = htons(first_len);
-               iph->frag_off = htons(IP_MF);
-diff -Nurd linux-2.6.24/net/ipv4/ip_sockglue.c linux-2.6.24-oxe810/net/ipv4/ip_sockglue.c
---- linux-2.6.24/net/ipv4/ip_sockglue.c        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/net/ipv4/ip_sockglue.c 2008-06-11 17:46:09.000000000 +0200
-@@ -514,11 +514,6 @@
-                       val &= ~3;
-                       val |= inet->tos & 3;
-               }
--              if (IPTOS_PREC(val) >= IPTOS_PREC_CRITIC_ECP &&
--                  !capable(CAP_NET_ADMIN)) {
--                      err = -EPERM;
--                      break;
--              }
-               if (inet->tos != val) {
-                       inet->tos = val;
-                       sk->sk_priority = rt_tos2priority(val);
-diff -Nurd linux-2.6.24/net/ipv4/ipcomp.c linux-2.6.24-oxe810/net/ipv4/ipcomp.c
---- linux-2.6.24/net/ipv4/ipcomp.c     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/net/ipv4/ipcomp.c      2008-06-11 17:46:09.000000000 +0200
-@@ -74,6 +74,7 @@
- static int ipcomp_input(struct xfrm_state *x, struct sk_buff *skb)
- {
-+      int nexthdr;
-       int err = -ENOMEM;
-       struct ip_comp_hdr *ipch;
-@@ -84,13 +85,15 @@
-       /* Remove ipcomp header and decompress original payload */
-       ipch = (void *)skb->data;
-+      nexthdr = ipch->nexthdr;
-+
-       skb->transport_header = skb->network_header + sizeof(*ipch);
-       __skb_pull(skb, sizeof(*ipch));
-       err = ipcomp_decompress(x, skb);
-       if (err)
-               goto out;
--      err = ipch->nexthdr;
-+      err = nexthdr;
- out:
-       return err;
-@@ -105,8 +108,11 @@
-       const int cpu = get_cpu();
-       u8 *scratch = *per_cpu_ptr(ipcomp_scratches, cpu);
-       struct crypto_comp *tfm = *per_cpu_ptr(ipcd->tfms, cpu);
--      int err = crypto_comp_compress(tfm, start, plen, scratch, &dlen);
-+      int err;
-+      local_bh_disable();
-+      err = crypto_comp_compress(tfm, start, plen, scratch, &dlen);
-+      local_bh_enable();
-       if (err)
-               goto out;
-diff -Nurd linux-2.6.24/net/ipv4/ipconfig.c linux-2.6.24-oxe810/net/ipv4/ipconfig.c
---- linux-2.6.24/net/ipv4/ipconfig.c   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/net/ipv4/ipconfig.c    2008-06-11 17:46:09.000000000 +0200
-@@ -739,9 +739,9 @@
-               printk("Unknown ARP type 0x%04x for device %s\n", dev->type, dev->name);
-               b->htype = dev->type; /* can cause undefined behavior */
-       }
-+
-+      /* server_ip and your_ip address are both already zero per RFC2131 */
-       b->hlen = dev->addr_len;
--      b->your_ip = NONE;
--      b->server_ip = NONE;
-       memcpy(b->hw_addr, dev->dev_addr, dev->addr_len);
-       b->secs = htons(jiffies_diff / HZ);
-       b->xid = d->xid;
-diff -Nurd linux-2.6.24/net/ipv4/netfilter/arpt_mangle.c linux-2.6.24-oxe810/net/ipv4/netfilter/arpt_mangle.c
---- linux-2.6.24/net/ipv4/netfilter/arpt_mangle.c      2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/net/ipv4/netfilter/arpt_mangle.c       2008-06-11 17:46:07.000000000 +0200
-@@ -19,7 +19,7 @@
-       unsigned char *arpptr;
-       int pln, hln;
--      if (skb_make_writable(skb, skb->len))
-+      if (!skb_make_writable(skb, skb->len))
-               return NF_DROP;
-       arp = arp_hdr(skb);
-diff -Nurd linux-2.6.24/net/ipv4/netfilter/ip_queue.c linux-2.6.24-oxe810/net/ipv4/netfilter/ip_queue.c
---- linux-2.6.24/net/ipv4/netfilter/ip_queue.c 2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/net/ipv4/netfilter/ip_queue.c  2008-06-11 17:46:07.000000000 +0200
-@@ -336,8 +336,8 @@
- ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct ipq_queue_entry *e)
- {
-       int diff;
--      int err;
-       struct iphdr *user_iph = (struct iphdr *)v->payload;
-+      struct sk_buff *nskb;
-       if (v->data_len < sizeof(*user_iph))
-               return 0;
-@@ -349,14 +349,16 @@
-               if (v->data_len > 0xFFFF)
-                       return -EINVAL;
-               if (diff > skb_tailroom(e->skb)) {
--                      err = pskb_expand_head(e->skb, 0,
-+                      nskb = skb_copy_expand(e->skb, 0,
-                                              diff - skb_tailroom(e->skb),
-                                              GFP_ATOMIC);
--                      if (err) {
-+                      if (!nskb) {
-                               printk(KERN_WARNING "ip_queue: error "
--                                    "in mangle, dropping packet: %d\n", -err);
--                              return err;
-+                                    "in mangle, dropping packet\n");
-+                              return -ENOMEM;
-                       }
-+                      kfree_skb(e->skb);
-+                      e->skb = nskb;
-               }
-               skb_put(e->skb, diff);
-       }
-diff -Nurd linux-2.6.24/net/ipv4/sysctl_net_ipv4.c linux-2.6.24-oxe810/net/ipv4/sysctl_net_ipv4.c
---- linux-2.6.24/net/ipv4/sysctl_net_ipv4.c    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/net/ipv4/sysctl_net_ipv4.c     2008-06-11 17:46:09.000000000 +0200
-@@ -248,7 +248,7 @@
-       tcp_get_available_congestion_control(tbl.data, tbl.maxlen);
-       ret = sysctl_string(&tbl, name, nlen, oldval, oldlenp, newval, newlen);
--      if (ret == 0 && newval && newlen)
-+      if (ret == 1 && newval && newlen)
-               ret = tcp_set_allowed_congestion_control(tbl.data);
-       kfree(tbl.data);
-diff -Nurd linux-2.6.24/net/ipv4/tcp.c linux-2.6.24-oxe810/net/ipv4/tcp.c
---- linux-2.6.24/net/ipv4/tcp.c        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/net/ipv4/tcp.c 2008-06-11 17:46:09.000000000 +0200
+diff -Nurd linux-2.6.24.4/net/ipv4/tcp.c linux-2.6.24/net/ipv4/tcp.c
+--- linux-2.6.24.4/net/ipv4/tcp.c      2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/net/ipv4/tcp.c        2010-01-14 14:01:15.000000000 +0100
 @@ -269,6 +269,8 @@
  #include <asm/uaccess.h>
  #include <asm/ioctls.h>
@@ -55571,355 +49365,9 @@ diff -Nurd linux-2.6.24/net/ipv4/tcp.c linux-2.6.24-oxe810/net/ipv4/tcp.c
  #define TCP_PAGE(sk)  (sk->sk_sndmsg_page)
  #define TCP_OFF(sk)   (sk->sk_sndmsg_off)
  
-diff -Nurd linux-2.6.24/net/ipv4/xfrm4_tunnel.c linux-2.6.24-oxe810/net/ipv4/xfrm4_tunnel.c
---- linux-2.6.24/net/ipv4/xfrm4_tunnel.c       2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/net/ipv4/xfrm4_tunnel.c        2008-06-11 17:46:09.000000000 +0200
-@@ -50,7 +50,7 @@
- static int xfrm_tunnel_rcv(struct sk_buff *skb)
- {
--      return xfrm4_rcv_spi(skb, IPPROTO_IP, ip_hdr(skb)->saddr);
-+      return xfrm4_rcv_spi(skb, IPPROTO_IPIP, ip_hdr(skb)->saddr);
- }
- static int xfrm_tunnel_err(struct sk_buff *skb, u32 info)
-diff -Nurd linux-2.6.24/net/ipv6/ip6_output.c linux-2.6.24-oxe810/net/ipv6/ip6_output.c
---- linux-2.6.24/net/ipv6/ip6_output.c 2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/net/ipv6/ip6_output.c  2008-06-11 17:46:11.000000000 +0200
-@@ -593,7 +593,7 @@
-        * or if the skb it not generated by a local socket.  (This last
-        * check should be redundant, but it's free.)
-        */
--      if (!np || np->pmtudisc >= IPV6_PMTUDISC_DO) {
-+      if (!skb->local_df) {
-               skb->dev = skb->dst->dev;
-               icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev);
-               IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGFAILS);
-@@ -609,6 +609,7 @@
-       if (skb_shinfo(skb)->frag_list) {
-               int first_len = skb_pagelen(skb);
-+              int truesizes = 0;
-               if (first_len - hlen > mtu ||
-                   ((first_len - hlen) & 7) ||
-@@ -631,7 +632,7 @@
-                               sock_hold(skb->sk);
-                               frag->sk = skb->sk;
-                               frag->destructor = sock_wfree;
--                              skb->truesize -= frag->truesize;
-+                              truesizes += frag->truesize;
-                       }
-               }
-@@ -662,6 +663,7 @@
-               first_len = skb_pagelen(skb);
-               skb->data_len = first_len - skb_headlen(skb);
-+              skb->truesize -= truesizes;
-               skb->len = first_len;
-               ipv6_hdr(skb)->payload_len = htons(first_len -
-                                                  sizeof(struct ipv6hdr));
-@@ -1387,6 +1389,10 @@
-               tmp_skb->sk = NULL;
-       }
-+      /* Allow local fragmentation. */
-+      if (np->pmtudisc < IPV6_PMTUDISC_DO)
-+              skb->local_df = 1;
-+
-       ipv6_addr_copy(final_dst, &fl->fl6_dst);
-       __skb_pull(skb, skb_network_header_len(skb));
-       if (opt && opt->opt_flen)
-diff -Nurd linux-2.6.24/net/ipv6/ip6_tunnel.c linux-2.6.24-oxe810/net/ipv6/ip6_tunnel.c
---- linux-2.6.24/net/ipv6/ip6_tunnel.c 2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/net/ipv6/ip6_tunnel.c  2008-06-11 17:46:11.000000000 +0200
-@@ -550,6 +550,7 @@
-                       ip_rt_put(rt);
-                       goto out;
-               }
-+              skb2->dst = (struct dst_entry *)rt;
-       } else {
-               ip_rt_put(rt);
-               if (ip_route_input(skb2, eiph->daddr, eiph->saddr, eiph->tos,
-diff -Nurd linux-2.6.24/net/ipv6/ipcomp6.c linux-2.6.24-oxe810/net/ipv6/ipcomp6.c
---- linux-2.6.24/net/ipv6/ipcomp6.c    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/net/ipv6/ipcomp6.c     2008-06-11 17:46:11.000000000 +0200
-@@ -64,6 +64,7 @@
- static int ipcomp6_input(struct xfrm_state *x, struct sk_buff *skb)
- {
-+      int nexthdr;
-       int err = -ENOMEM;
-       struct ip_comp_hdr *ipch;
-       int plen, dlen;
-@@ -79,6 +80,8 @@
-       /* Remove ipcomp header and decompress original payload */
-       ipch = (void *)skb->data;
-+      nexthdr = ipch->nexthdr;
-+
-       skb->transport_header = skb->network_header + sizeof(*ipch);
-       __skb_pull(skb, sizeof(*ipch));
-@@ -108,7 +111,7 @@
-       skb->truesize += dlen - plen;
-       __skb_put(skb, dlen - plen);
-       skb_copy_to_linear_data(skb, scratch, dlen);
--      err = ipch->nexthdr;
-+      err = nexthdr;
- out_put_cpu:
-       put_cpu();
-@@ -143,7 +146,9 @@
-       scratch = *per_cpu_ptr(ipcomp6_scratches, cpu);
-       tfm = *per_cpu_ptr(ipcd->tfms, cpu);
-+      local_bh_disable();
-       err = crypto_comp_compress(tfm, start, plen, scratch, &dlen);
-+      local_bh_enable();
-       if (err || (dlen + sizeof(*ipch)) >= plen) {
-               put_cpu();
-               goto out_ok;
-diff -Nurd linux-2.6.24/net/ipv6/netfilter/ip6_queue.c linux-2.6.24-oxe810/net/ipv6/netfilter/ip6_queue.c
---- linux-2.6.24/net/ipv6/netfilter/ip6_queue.c        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/net/ipv6/netfilter/ip6_queue.c 2008-06-11 17:46:10.000000000 +0200
-@@ -333,8 +333,8 @@
- ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct ipq_queue_entry *e)
- {
-       int diff;
--      int err;
-       struct ipv6hdr *user_iph = (struct ipv6hdr *)v->payload;
-+      struct sk_buff *nskb;
-       if (v->data_len < sizeof(*user_iph))
-               return 0;
-@@ -346,14 +346,16 @@
-               if (v->data_len > 0xFFFF)
-                       return -EINVAL;
-               if (diff > skb_tailroom(e->skb)) {
--                      err = pskb_expand_head(e->skb, 0,
-+                      nskb = skb_copy_expand(e->skb, 0,
-                                              diff - skb_tailroom(e->skb),
-                                              GFP_ATOMIC);
--                      if (err) {
-+                      if (!nskb) {
-                               printk(KERN_WARNING "ip6_queue: OOM "
-                                     "in mangle, dropping packet\n");
--                              return err;
-+                              return -ENOMEM;
-                       }
-+                      kfree_skb(e->skb);
-+                      e->skb = nskb;
-               }
-               skb_put(e->skb, diff);
-       }
-diff -Nurd linux-2.6.24/net/ipv6/xfrm6_output.c linux-2.6.24-oxe810/net/ipv6/xfrm6_output.c
---- linux-2.6.24/net/ipv6/xfrm6_output.c       2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/net/ipv6/xfrm6_output.c        2008-06-11 17:46:11.000000000 +0200
-@@ -34,7 +34,7 @@
-       if (mtu < IPV6_MIN_MTU)
-               mtu = IPV6_MIN_MTU;
--      if (skb->len > mtu) {
-+      if (!skb->local_df && skb->len > mtu) {
-               skb->dev = dst->dev;
-               icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev);
-               ret = -EMSGSIZE;
-diff -Nurd linux-2.6.24/net/netfilter/nf_conntrack_proto_tcp.c linux-2.6.24-oxe810/net/netfilter/nf_conntrack_proto_tcp.c
---- linux-2.6.24/net/netfilter/nf_conntrack_proto_tcp.c        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/net/netfilter/nf_conntrack_proto_tcp.c 2008-06-11 17:46:00.000000000 +0200
-@@ -135,7 +135,7 @@
-  * CLOSE_WAIT:        ACK seen (after FIN)
-  * LAST_ACK:  FIN seen (after FIN)
-  * TIME_WAIT: last ACK seen
-- * CLOSE:     closed connection
-+ * CLOSE:     closed connection (RST)
-  *
-  * LISTEN state is not used.
-  *
-@@ -834,8 +834,21 @@
-       case TCP_CONNTRACK_SYN_SENT:
-               if (old_state < TCP_CONNTRACK_TIME_WAIT)
-                       break;
--              if ((conntrack->proto.tcp.seen[!dir].flags &
--                      IP_CT_TCP_FLAG_CLOSE_INIT)
-+              /* RFC 1122: "When a connection is closed actively,
-+               * it MUST linger in TIME-WAIT state for a time 2xMSL
-+               * (Maximum Segment Lifetime). However, it MAY accept
-+               * a new SYN from the remote TCP to reopen the connection
-+               * directly from TIME-WAIT state, if..."
-+               * We ignore the conditions because we are in the
-+               * TIME-WAIT state anyway.
-+               *
-+               * Handle aborted connections: we and the server
-+               * think there is an existing connection but the client
-+               * aborts it and starts a new one.
-+               */
-+              if (((conntrack->proto.tcp.seen[dir].flags
-+                    | conntrack->proto.tcp.seen[!dir].flags)
-+                   & IP_CT_TCP_FLAG_CLOSE_INIT)
-                   || (conntrack->proto.tcp.last_dir == dir
-                       && conntrack->proto.tcp.last_index == TCP_RST_SET)) {
-                       /* Attempt to reopen a closed/aborted connection.
-@@ -848,18 +861,25 @@
-               }
-               /* Fall through */
-       case TCP_CONNTRACK_IGNORE:
--              /* Ignored packets:
-+              /* Ignored packets: 
-+               *
-+               * Our connection entry may be out of sync, so ignore
-+               * packets which may signal the real connection between
-+               * the client and the server.
-                *
-                * a) SYN in ORIGINAL
-                * b) SYN/ACK in REPLY
-                * c) ACK in reply direction after initial SYN in original.
-+               *
-+               * If the ignored packet is invalid, the receiver will send 
-+               * a RST we'll catch below.
-                */
-               if (index == TCP_SYNACK_SET
-                   && conntrack->proto.tcp.last_index == TCP_SYN_SET
-                   && conntrack->proto.tcp.last_dir != dir
-                   && ntohl(th->ack_seq) ==
-                            conntrack->proto.tcp.last_end) {
--                      /* This SYN/ACK acknowledges a SYN that we earlier
-+                      /* b) This SYN/ACK acknowledges a SYN that we earlier
-                        * ignored as invalid. This means that the client and
-                        * the server are both in sync, while the firewall is
-                        * not. We kill this session and block the SYN/ACK so
-@@ -884,7 +904,7 @@
-               write_unlock_bh(&tcp_lock);
-               if (LOG_INVALID(IPPROTO_TCP))
-                       nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
--                                "nf_ct_tcp: invalid packed ignored ");
-+                                "nf_ct_tcp: invalid packet ignored ");
-               return NF_ACCEPT;
-       case TCP_CONNTRACK_MAX:
-               /* Invalid packet */
-@@ -938,8 +958,7 @@
-       conntrack->proto.tcp.state = new_state;
-       if (old_state != new_state
--          && (new_state == TCP_CONNTRACK_FIN_WAIT
--              || new_state == TCP_CONNTRACK_CLOSE))
-+          && new_state == TCP_CONNTRACK_FIN_WAIT)
-               conntrack->proto.tcp.seen[dir].flags |= IP_CT_TCP_FLAG_CLOSE_INIT;
-       timeout = conntrack->proto.tcp.retrans >= nf_ct_tcp_max_retrans
-                 && *tcp_timeouts[new_state] > nf_ct_tcp_timeout_max_retrans
-diff -Nurd linux-2.6.24/net/netfilter/nfnetlink_log.c linux-2.6.24-oxe810/net/netfilter/nfnetlink_log.c
---- linux-2.6.24/net/netfilter/nfnetlink_log.c 2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/net/netfilter/nfnetlink_log.c  2008-06-11 17:46:00.000000000 +0200
-@@ -594,7 +594,7 @@
-       /* FIXME: do we want to make the size calculation conditional based on
-        * what is actually present?  way more branches and checks, but more
-        * memory efficient... */
--      size =    NLMSG_ALIGN(sizeof(struct nfgenmsg))
-+      size =    NLMSG_SPACE(sizeof(struct nfgenmsg))
-               + nla_total_size(sizeof(struct nfulnl_msg_packet_hdr))
-               + nla_total_size(sizeof(u_int32_t))     /* ifindex */
-               + nla_total_size(sizeof(u_int32_t))     /* ifindex */
-diff -Nurd linux-2.6.24/net/netfilter/nfnetlink_queue.c linux-2.6.24-oxe810/net/netfilter/nfnetlink_queue.c
---- linux-2.6.24/net/netfilter/nfnetlink_queue.c       2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/net/netfilter/nfnetlink_queue.c        2008-06-11 17:46:00.000000000 +0200
-@@ -353,7 +353,7 @@
-       QDEBUG("entered\n");
--      size =    NLMSG_ALIGN(sizeof(struct nfgenmsg))
-+      size =    NLMSG_SPACE(sizeof(struct nfgenmsg))
-               + nla_total_size(sizeof(struct nfqnl_msg_packet_hdr))
-               + nla_total_size(sizeof(u_int32_t))     /* ifindex */
-               + nla_total_size(sizeof(u_int32_t))     /* ifindex */
-@@ -616,8 +616,8 @@
- static int
- nfqnl_mangle(void *data, int data_len, struct nfqnl_queue_entry *e)
- {
-+      struct sk_buff *nskb;
-       int diff;
--      int err;
-       diff = data_len - e->skb->len;
-       if (diff < 0) {
-@@ -627,14 +627,16 @@
-               if (data_len > 0xFFFF)
-                       return -EINVAL;
-               if (diff > skb_tailroom(e->skb)) {
--                      err = pskb_expand_head(e->skb, 0,
-+                      nskb = skb_copy_expand(e->skb, 0,
-                                              diff - skb_tailroom(e->skb),
-                                              GFP_ATOMIC);
--                      if (err) {
-+                      if (!nskb) {
-                               printk(KERN_WARNING "nf_queue: OOM "
-                                     "in mangle, dropping packet\n");
--                              return err;
-+                              return -ENOMEM;
-                       }
-+                      kfree_skb(e->skb);
-+                      e->skb = nskb;
-               }
-               skb_put(e->skb, diff);
-       }
-diff -Nurd linux-2.6.24/net/netfilter/xt_time.c linux-2.6.24-oxe810/net/netfilter/xt_time.c
---- linux-2.6.24/net/netfilter/xt_time.c       2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/net/netfilter/xt_time.c        2008-06-11 17:46:00.000000000 +0200
-@@ -95,8 +95,11 @@
-        */
-       r->dse = time / 86400;
--      /* 1970-01-01 (w=0) was a Thursday (4). */
--      r->weekday = (4 + r->dse) % 7;
-+      /*
-+       * 1970-01-01 (w=0) was a Thursday (4).
-+       * -1 and +1 map Sunday properly onto 7.
-+       */
-+      r->weekday = (4 + r->dse - 1) % 7 + 1;
- }
- static void localtime_3(struct xtm *r, time_t time)
-diff -Nurd linux-2.6.24/net/sched/em_meta.c linux-2.6.24-oxe810/net/sched/em_meta.c
---- linux-2.6.24/net/sched/em_meta.c   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/net/sched/em_meta.c    2008-06-11 17:45:56.000000000 +0200
-@@ -719,11 +719,13 @@
- static inline void meta_delete(struct meta_match *meta)
- {
--      struct meta_type_ops *ops = meta_type_ops(&meta->lvalue);
-+      if (meta) {
-+              struct meta_type_ops *ops = meta_type_ops(&meta->lvalue);
--      if (ops && ops->destroy) {
--              ops->destroy(&meta->lvalue);
--              ops->destroy(&meta->rvalue);
-+              if (ops && ops->destroy) {
-+                      ops->destroy(&meta->lvalue);
-+                      ops->destroy(&meta->rvalue);
-+              }
-       }
-       kfree(meta);
-diff -Nurd linux-2.6.24/net/sched/ematch.c linux-2.6.24-oxe810/net/sched/ematch.c
---- linux-2.6.24/net/sched/ematch.c    2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/net/sched/ematch.c     2008-06-11 17:45:56.000000000 +0200
-@@ -305,10 +305,9 @@
-       struct tcf_ematch_tree_hdr *tree_hdr;
-       struct tcf_ematch *em;
--      if (!rta) {
--              memset(tree, 0, sizeof(*tree));
-+      memset(tree, 0, sizeof(*tree));
-+      if (!rta)
-               return 0;
--      }
-       if (rtattr_parse_nested(tb, TCA_EMATCH_TREE_MAX, rta) < 0)
-               goto errout;
-diff -Nurd linux-2.6.24/net/socket.c linux-2.6.24-oxe810/net/socket.c
---- linux-2.6.24/net/socket.c  2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/net/socket.c   2008-06-11 17:46:19.000000000 +0200
+diff -Nurd linux-2.6.24.4/net/socket.c linux-2.6.24/net/socket.c
+--- linux-2.6.24.4/net/socket.c        2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/net/socket.c  2010-01-14 14:01:15.000000000 +0100
 @@ -113,6 +113,9 @@
  static ssize_t sock_sendpage(struct file *file, struct page *page,
                             int offset, size_t size, loff_t *ppos, int more);
@@ -55960,21 +49408,9 @@ diff -Nurd linux-2.6.24/net/socket.c linux-2.6.24-oxe810/net/socket.c
  static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb,
                                         struct sock_iocb *siocb)
  {
-diff -Nurd linux-2.6.24/scripts/mod/file2alias.c linux-2.6.24-oxe810/scripts/mod/file2alias.c
---- linux-2.6.24/scripts/mod/file2alias.c      2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/scripts/mod/file2alias.c       2008-06-11 17:46:20.000000000 +0200
-@@ -155,7 +155,7 @@
-        * Some modules (visor) have empty slots as placeholder for
-        * run-time specification that results in catch-all alias
-        */
--      if (!(id->idVendor | id->bDeviceClass | id->bInterfaceClass))
-+      if (!(id->idVendor | id->idProduct | id->bDeviceClass | id->bInterfaceClass))
-               return;
-       /* Convert numeric bcdDevice range into fnmatch-able pattern(s) */
-diff -Nurd linux-2.6.24/security/Kconfig linux-2.6.24-oxe810/security/Kconfig
---- linux-2.6.24/security/Kconfig      2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/security/Kconfig       2008-06-11 17:46:44.000000000 +0200
+diff -Nurd linux-2.6.24.4/security/Kconfig linux-2.6.24/security/Kconfig
+--- linux-2.6.24.4/security/Kconfig    2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/security/Kconfig      2010-01-14 14:01:15.000000000 +0100
 @@ -103,6 +103,32 @@
          
          If you are unsure how to answer this question, answer N.
@@ -56008,9 +49444,9 @@ diff -Nurd linux-2.6.24/security/Kconfig linux-2.6.24-oxe810/security/Kconfig
  source security/selinux/Kconfig
  
  endmenu
-diff -Nurd linux-2.6.24/security/Makefile linux-2.6.24-oxe810/security/Makefile
---- linux-2.6.24/security/Makefile     2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/security/Makefile      2008-06-11 17:46:44.000000000 +0200
+diff -Nurd linux-2.6.24.4/security/Makefile linux-2.6.24/security/Makefile
+--- linux-2.6.24.4/security/Makefile   2008-03-24 19:49:18.000000000 +0100
++++ linux-2.6.24/security/Makefile     2010-01-14 14:01:15.000000000 +0100
 @@ -12,6 +12,7 @@
  
  # Object file lists
@@ -56019,54 +49455,9 @@ diff -Nurd linux-2.6.24/security/Makefile linux-2.6.24-oxe810/security/Makefile
  # Must precede capability.o in order to stack properly.
  obj-$(CONFIG_SECURITY_SELINUX)                += selinux/built-in.o
  obj-$(CONFIG_SECURITY_CAPABILITIES)   += commoncap.o capability.o
-diff -Nurd linux-2.6.24/security/commoncap.c linux-2.6.24-oxe810/security/commoncap.c
---- linux-2.6.24/security/commoncap.c  2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/security/commoncap.c   2008-06-11 17:46:44.000000000 +0200
-@@ -539,7 +539,7 @@
-        * allowed.
-        * We must preserve legacy signal behavior in this case.
-        */
--      if (p->euid == 0 && p->uid == current->uid)
-+      if (p->uid == current->uid)
-               return 0;
-       /* sigcont is permitted within same session */
-diff -Nurd linux-2.6.24/security/selinux/ss/services.c linux-2.6.24-oxe810/security/selinux/ss/services.c
---- linux-2.6.24/security/selinux/ss/services.c        2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/security/selinux/ss/services.c 2008-06-11 17:46:43.000000000 +0200
-@@ -1744,6 +1744,9 @@
-       struct ocontext *c;
-       int rc = 0, cmp = 0;
-+      while (path[0] == '/' && path[1] == '/')
-+              path++;
-+
-       POLICY_RDLOCK;
-       for (genfs = policydb.genfs; genfs; genfs = genfs->next) {
-@@ -2626,7 +2629,6 @@
- netlbl_sid_to_secattr_failure:
-       POLICY_RDUNLOCK;
--      netlbl_secattr_destroy(secattr);
-       return rc;
- }
- #endif /* CONFIG_NETLABEL */
-diff -Nurd linux-2.6.24/security/trustees/Makefile linux-2.6.24-oxe810/security/trustees/Makefile
---- linux-2.6.24/security/trustees/Makefile    1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/security/trustees/Makefile     2008-06-11 17:46:44.000000000 +0200
-@@ -0,0 +1,8 @@
-+ifeq ($(CONFIG_SECURITY_TRUSTEES_DEBUG),y)
-+      EXTRA_CFLAGS += -DTRUSTEES_DEBUG
-+endif
-+
-+obj-$(CONFIG_SECURITY_TRUSTEES) := trustees.o
-+trustees-objs := \
-+      security.o fs.o \
-+      init.o funcs.o ../commoncap.o
-diff -Nurd linux-2.6.24/security/trustees/fs.c linux-2.6.24-oxe810/security/trustees/fs.c
---- linux-2.6.24/security/trustees/fs.c        1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/security/trustees/fs.c 2008-06-11 17:46:44.000000000 +0200
+diff -Nurd linux-2.6.24.4/security/trustees/fs.c linux-2.6.24/security/trustees/fs.c
+--- linux-2.6.24.4/security/trustees/fs.c      1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/security/trustees/fs.c        2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,273 @@
 +/*
 + * Trustees ACL Project
@@ -56341,9 +49732,9 @@ diff -Nurd linux-2.6.24/security/trustees/fs.c linux-2.6.24-oxe810/security/trus
 +
 +      return count;
 +}
-diff -Nurd linux-2.6.24/security/trustees/funcs.c linux-2.6.24-oxe810/security/trustees/funcs.c
---- linux-2.6.24/security/trustees/funcs.c     1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/security/trustees/funcs.c      2008-06-11 17:46:44.000000000 +0200
+diff -Nurd linux-2.6.24.4/security/trustees/funcs.c linux-2.6.24/security/trustees/funcs.c
+--- linux-2.6.24.4/security/trustees/funcs.c   1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/security/trustees/funcs.c     2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,810 @@
 +/*
 + * Trustees ACL Project
@@ -57155,9 +50546,9 @@ diff -Nurd linux-2.6.24/security/trustees/funcs.c linux-2.6.24-oxe810/security/t
 +
 +      return r;
 +}
-diff -Nurd linux-2.6.24/security/trustees/init.c linux-2.6.24-oxe810/security/trustees/init.c
---- linux-2.6.24/security/trustees/init.c      1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/security/trustees/init.c       2008-06-11 17:46:44.000000000 +0200
+diff -Nurd linux-2.6.24.4/security/trustees/init.c linux-2.6.24/security/trustees/init.c
+--- linux-2.6.24.4/security/trustees/init.c    1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/security/trustees/init.c      2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,57 @@
 +/*
 + * Trustees ACL Project
@@ -57216,9 +50607,9 @@ diff -Nurd linux-2.6.24/security/trustees/init.c linux-2.6.24-oxe810/security/tr
 +}
 +
 +fs_initcall(trustees_init);
-diff -Nurd linux-2.6.24/security/trustees/internal.h linux-2.6.24-oxe810/security/trustees/internal.h
---- linux-2.6.24/security/trustees/internal.h  1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/security/trustees/internal.h   2008-06-11 17:46:44.000000000 +0200
+diff -Nurd linux-2.6.24.4/security/trustees/internal.h linux-2.6.24/security/trustees/internal.h
+--- linux-2.6.24.4/security/trustees/internal.h        1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/security/trustees/internal.h  2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,100 @@
 +/*
 + * Trustees ACL Project
@@ -57320,9 +50711,21 @@ diff -Nurd linux-2.6.24/security/trustees/internal.h linux-2.6.24-oxe810/securit
 +
 +int trustees_init_security(void);
 +#endif                                /* _LINUX_TRUSTEES_H */
-diff -Nurd linux-2.6.24/security/trustees/security.c linux-2.6.24-oxe810/security/trustees/security.c
---- linux-2.6.24/security/trustees/security.c  1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.24-oxe810/security/trustees/security.c   2008-06-11 17:46:44.000000000 +0200
+diff -Nurd linux-2.6.24.4/security/trustees/Makefile linux-2.6.24/security/trustees/Makefile
+--- linux-2.6.24.4/security/trustees/Makefile  1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/security/trustees/Makefile    2010-01-14 14:01:15.000000000 +0100
+@@ -0,0 +1,8 @@
++ifeq ($(CONFIG_SECURITY_TRUSTEES_DEBUG),y)
++      EXTRA_CFLAGS += -DTRUSTEES_DEBUG
++endif
++
++obj-$(CONFIG_SECURITY_TRUSTEES) := trustees.o
++trustees-objs := \
++      security.o fs.o \
++      init.o funcs.o ../commoncap.o
+diff -Nurd linux-2.6.24.4/security/trustees/security.c linux-2.6.24/security/trustees/security.c
+--- linux-2.6.24.4/security/trustees/security.c        1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.24/security/trustees/security.c  2010-01-14 14:01:15.000000000 +0100
 @@ -0,0 +1,423 @@
 +/*
 + * Trustees ACL Project
@@ -57747,58 +51150,3 @@ diff -Nurd linux-2.6.24/security/trustees/security.c linux-2.6.24-oxe810/securit
 +
 +      return 0;
 +}
-diff -Nurd linux-2.6.24/sound/oss/via82cxxx_audio.c linux-2.6.24-oxe810/sound/oss/via82cxxx_audio.c
---- linux-2.6.24/sound/oss/via82cxxx_audio.c   2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/sound/oss/via82cxxx_audio.c    2008-06-11 17:46:29.000000000 +0200
-@@ -2104,6 +2104,7 @@
- {
-       struct via_info *card = vma->vm_private_data;
-       struct via_channel *chan = &card->ch_out;
-+      unsigned long max_bufs;
-       struct page *dmapage;
-       unsigned long pgoff;
-       int rd, wr;
-@@ -2127,14 +2128,11 @@
-       rd = card->ch_in.is_mapped;
-       wr = card->ch_out.is_mapped;
--#ifndef VIA_NDEBUG
--      {
--      unsigned long max_bufs = chan->frag_number;
--      if (rd && wr) max_bufs *= 2;
--      /* via_dsp_mmap() should ensure this */
--      assert (pgoff < max_bufs);
--      }
--#endif
-+      max_bufs = chan->frag_number;
-+      if (rd && wr)
-+              max_bufs *= 2;
-+      if (pgoff >= max_bufs)
-+              return NOPAGE_SIGBUS;
-       /* if full-duplex (read+write) and we have two sets of bufs,
-        * then the playback buffers come first, sez soundcard.c */
-diff -Nurd linux-2.6.24/sound/usb/usx2y/usX2Yhwdep.c linux-2.6.24-oxe810/sound/usb/usx2y/usX2Yhwdep.c
---- linux-2.6.24/sound/usb/usx2y/usX2Yhwdep.c  2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/sound/usb/usx2y/usX2Yhwdep.c   2008-06-11 17:46:26.000000000 +0200
-@@ -88,7 +88,7 @@
-               us428->us428ctls_sharedmem->CtlSnapShotLast = -2;
-       }
-       area->vm_ops = &us428ctls_vm_ops;
--      area->vm_flags |= VM_RESERVED;
-+      area->vm_flags |= VM_RESERVED | VM_DONTEXPAND;
-       area->vm_private_data = hw->private_data;
-       return 0;
- }
-diff -Nurd linux-2.6.24/sound/usb/usx2y/usx2yhwdeppcm.c linux-2.6.24-oxe810/sound/usb/usx2y/usx2yhwdeppcm.c
---- linux-2.6.24/sound/usb/usx2y/usx2yhwdeppcm.c       2008-01-24 23:58:37.000000000 +0100
-+++ linux-2.6.24-oxe810/sound/usb/usx2y/usx2yhwdeppcm.c        2008-06-11 17:46:26.000000000 +0200
-@@ -728,7 +728,7 @@
-               return -ENODEV;
-       }
-       area->vm_ops = &snd_usX2Y_hwdep_pcm_vm_ops;
--      area->vm_flags |= VM_RESERVED;
-+      area->vm_flags |= VM_RESERVED | VM_DONTEXPAND;
-       area->vm_private_data = hw->private_data;
-       return 0;
- }